Problem/Motivation
Changes while moving filefield to core removed the ability for administrators to allow all file extensions in file fields. While greatly improving security for sites which allow end users to submit files, on single- or few-user sites it is incredibly difficult to manually allow an inclusive list of file extensions. There needs to be more flexibility in how file extensions are checked.
Proposed resolution
Provide a radio option above the allowed file extensions field for administrators to set either allow "Only the listed extensions" or "All extensions except those listed". Using "All extensions except those listed" with a blank list of extensions will allow all extensions. The default option will be "Only the listed extensions".
Remaining tasks
- Patch review
- Update form validation test (maybe?)
User interface changes
- New option fields on the File widget settings form
- Updated validation text for the File widget
Original report by droplet
edit field -> Allowed file extensions
no way to allow all file extensions
Comment | File | Size | Author |
---|---|---|---|
#124 | Screenshot 2019-05-15 at 14.24.58.png | 104.07 KB | maticb |
#119 | disallowed-extensions-997900-119.patch | 17.51 KB | AaronBauman |
#80 | i997900-80.patch | 17.59 KB | attiks |
#69 | disallowed-extensions-997900-69.patch | 17.58 KB | JamesK |
#65 | i997900-65.png | 63.41 KB | attiks |
Comments
Comment #1
BerdirI think that is by design. See #803926: File field shouldn't allow any file extension to be uploaded when the list of allowed extensions is left blank
Comment #2
droplet CreditAttribution: droplet commentedthanks
I hope we would add back this feature and do what dww said "type in something like
<insecure-allow-all>
" to allow all file extensions.for example, EXE is a dangerous extension, I wonder what's the different between I type them into the INPUT field than typing in
<insecure-allow-all>
Comment #3
yched CreditAttribution: yched commentedrecategorizing
Comment #4
Aeternum CreditAttribution: Aeternum commentedSubscribing.
This issue is really so painful when the only people with access to the file upload box are trusted users.
Comment #5
bluestarstudios CreditAttribution: bluestarstudios commentedSo if not being able to upload all extension types was done for security reasons it's understandable. However if under the "allowed extensions" field in your content type you try to specify the list of the most common Text, Video & Audio file formats you won't even get to the end of that list because the text field doesn't allow more than 128 characters!
This needs to be fixed ASAP, because if I'm trying to allow my clients to upload files for me, various files keep on being rejected ("File Type Not Allowed" errors) purely because I can't fit enough extensions into the "allowed extensions" field.
I'm bumping this to a "major" issue, because it's something that really has to be figured out. Thanks for your help everybody.
Comment #6
bluestarstudios CreditAttribution: bluestarstudios commentedI'm copying over a great post which should help support our case. This is comment #61 in the original #803926: File field shouldn't allow any file extension to be uploaded when the list of allowed extensions is left blank thread.
I among many others am also in need of this use-case scenario. A wildcard to allow all extensions or some other resolution is needed. I look forward to hearing some ideas soon. :)
Comment #7
Alan D. CreditAttribution: Alan D. commentedThe easiest fix would be to simply set a #maxlength property to something much higher than the default of 128, say 512. Not a great solution, but it should resolve the issue for 98% of users.
A complete helper module and allow all tags solution
This is a general request for feedback. This could be added to FileField UI Extras module.
To provide easy extension selection tags, like "<images>" and "<movies>" for example and the "<insecure-allow-all>" tags.
Possible tag list.
No interface, but have these set using variables:
And then it gets a bit nasty. The valid extension list would save extension tokens like __FILE_EXT_IMAGES__, and these need to be replaced before saving the uploaded file. A quick code scan showed that the following may be required:
Add an additional processor to managed_file to alter the file extension list sent to file.js (update
$element['upload']['#attached']['js'][1]['data']['file']['elements']['#-' . xxx . '-upload'])
).Overwrite the value callback (file_managed_file_value) to hook into the extension list before the file is saved, and also file_field_widget_value() which directly calls file_managed_file_value().
Love feedback on this from someone that knows the Drupal 7 file handling before trying myself. It would be easier to have an alter hook on the file extension before validation, but I guess that this is an API change which would not be allowed in Drupal 7 at this late stage...
Comment #8
bluestarstudios CreditAttribution: bluestarstudios commentedAlan! This sounds great! If only I knew enough coding to help. But I will support you mentally and with any testing necessary. :))
Thanks so much!
Comment #9
marcingy CreditAttribution: marcingy commentedThis is feature request and as such drupal 8.
Comment #10
bluestarstudios CreditAttribution: bluestarstudios commentedmarcingy, since Alan is suggesting to add this to the FileField UI Extras module (which I believe is a good idea) shouldn't we keep it at D7 and mark it as an issue relevant to that module from now on?
Comment #11
droplet CreditAttribution: droplet commentedIt's a bug or a task --> exist input "limited to 128 characters".
Comment #12
BartK CreditAttribution: BartK commentedI shouldn't have had to do this.
Here's a module that changes this in Drupal 7 back to Drupal 6's behavior. It also lengthens the allowed extensions field from 128 characters to 2048, just in case you have a long list of allowed extensions.
I'd love to do a better job on this, but I have other projects, and won't be adding any new features to this module. If someone wants to co-maintain it (or even take ownership of it), please contact me and let me know. This isn't exactly a complicated module -- it's 8 lines of code.
Here's the link:
http://drupal.org/project/allow_all_file_extensions
Comment #13
bluestarstudios CreditAttribution: bluestarstudios commentedBartK, Thanks so much for this module! Greatly appreciated!
Comment #14
JamesK CreditAttribution: JamesK commentedHere is a more general solution which we could implement in core.
Make it work similar to blocks with radio options: Only the listed extensions (default); All extensions except those listed. I would also suggest increasing the character limit for the field.
If anyone +1's this idea then I don't mind tackling it.
Comment #15
bkudrle CreditAttribution: bkudrle commentedJust for clarification here, since I was confused myself. In D6, one could go to example.com/admin/settings/uploads and set which file extensions are allowed to upload. In D7, the allowed file extensions are associated with the field type for each content type. For example, for the article content type, there is a field_image and the allowed extensions are set at example.com/admin/structure/types/manage/article/fields/field_image.
Hope that helps someone who might otherwise be confused about this.
Comment #16
bkudrle CreditAttribution: bkudrle commentedApologies for the multiple comments. Problems with the computer and apparently these comments cannot be deleted by the user.
Comment #20
glass.dimly CreditAttribution: glass.dimly commentedI contend that this is not a feature request this is a bug report.
Additionally, this is a bug report for Drupal 7.
1. This field is limited to 128 chars means only 32 extensions can be allowed (comment #6). Was this by design? Sorry, but if so this was not a good design decision.
2. Since when Drupal in the business of enforcing which files are and are not dangerous? .EXE files are only dangerous if installed manually, on a Windows machine.
Perhaps technically this is a feature request, but right now it is not possible to give users an omnipurpose upload. I say we allow a box to allow upload of any file.
Try explaining to a client why they can't upload a .zip or .pps file on their site because you could only allow 32 file types and you didn't think that would be a filetype they would choose.
For a site managed by group of trusted users, allowing them to upload any file is an appropriate decision and gives them their adult ability to decide which files are or are not dangerous for themselves. After all, we allow people to enable the PHP input filter which can foobar everything.
Happy to create a patch, in fact I will need to in order to deliver my clients a product that does not attempt to think for them.
Comment #21
tim.plunkettSee the backport policy.
Comment #22
BartK CreditAttribution: BartK commentedMy module fixes both of these issues:
http://drupal.org/project/allow_all_file_extensions
If you tried it in the past and ran into an issue with validation, that issue has been fixed. Also, the size of the text field is now 2048 characters, in case you need to specify a large number of file types.
Comment #23
glass.dimly CreditAttribution: glass.dimly commented@BartK, thanks much. This does the trick.
Comment #24
karschsp CreditAttribution: karschsp commentedAttached patch simply changes the maxlength on the Allowed file extensions field to 2048.
Comment #25
droplet CreditAttribution: droplet commented@24,
It allowed to enter more extension but still need a way to allow all of them.
any one support type in "allow-all-extension" to open the door?
Comment #26
JamesK CreditAttribution: JamesK commented@25 See #14
Comment #27
droplet CreditAttribution: droplet commented@Jamesk,
I missed a good idea. +1 for you.
Comment #28
karschsp CreditAttribution: karschsp commentedWhile I initially thought the blocks-like approach outlined in #14 sounded good, the more I thought about it, the less I liked it. There are thousands of potential extensions that a site admin would need to track if they were to choose: "Allow anything except these..."
Sure, it would be nice to allow any extension, but do you really run into that a lot?
Comment #29
karschsp CreditAttribution: karschsp commentedComment #30
droplet CreditAttribution: droplet commented@karschsp,
Myself always allow all extension on files upload and see @#20. It's crazy to tell myself or client to type in hundreds extension
Without type in something in "Allow anything except these...", that would be ALLOW ALL.
Since this issue created by me & the topic is clearly about seek a way to all allow extension.
Sorry, back to needs work. It's willing to fix them together or a separated issue for fixing the input maxlength only.
(a separated issue for input maxlength is good because i think ALLOW ALL won't be backport to D7 but maxlengh will do.)
Comment #31
karschsp CreditAttribution: karschsp commentedI'm not saying it's not a valid use case, I'm just trying to find the best way to implement it without opening a gaping security hole. There may not be a way...
Would "*" in that field work?
Comment #32
glass.dimly CreditAttribution: glass.dimly commentedThe "gaping security hole" already exists. A dev can just allow .php file or .exe files. ;)
If you want to start babysitting, why not check to disallow those, too?
My point is that it should be possible to configure Drupal to be insecure, but that Drupal should default to secure configurations and warn about insecure ones.
Comment #33
BartK CreditAttribution: BartK commentedI'm all in favor of having this default closed, but it's unacceptable not to allow the administrator to override that. If I, as a web administrator, would like to allow myself to upload files of any type, Drupal ought trust me to be smart enough to make that decision. A strongly worded warning would be far better.
Comment #34
JamesK CreditAttribution: JamesK commentedI'll give this a shot tomorrow.
Comment #35
JamesK CreditAttribution: JamesK commentedComment #37
JamesK CreditAttribution: JamesK commentedLets try to make tests not break this time.
(also renamed patch)
Comment #38
JamesK CreditAttribution: JamesK commentedComment #40
JamesK CreditAttribution: JamesK commentedthere is always a better way...
Comment #40.0
JamesK CreditAttribution: JamesK commentedFull issue summary
Comment #41
Alan D. CreditAttribution: Alan D. commentedWas #24 committed? This should be added as a workaround until a better solution is added IMHO.
A whitelist / blacklist approach looks ok, but most users would have difficulty deciding what are the files that should be excluded. AKA, how many users would know what extensions that their web server would execute... ASP, CF, PHP, PHP4, .... The blacklist as it currently stands is also deficient in this regards.
Comment #42
kking CreditAttribution: kking commentedReplaced:
+const fileAllowExtensionsListed = 0;
+const fileAllowExtensionsNotListed = 1;
With:
+var fileAllowExtensionsListed = 0;
+var fileAllowExtensionsNotListed = 1;
As const is not supported by IE 6/7/8/9
Reference: https://developer.mozilla.org/en/JavaScript/Reference/Statements/const
Comment #44
kking CreditAttribution: kking commentedRemoving whitespace
Comment #45
kking CreditAttribution: kking commentedTake 3
Comment #46
kking CreditAttribution: kking commentedSetting to needs review
Comment #47
webchickSorry, but this isn't major. It's also a feature request. There is a workaround in contrib for people who need this functionality today (thanks, BartK!).
Extending the length of the file extensions field looks like a nice, uncontroversial change that could be handled in a separate issue.
Comment #48
justindodge CreditAttribution: justindodge commentedJust want to throw in my $0.02 and say I wholly agree with these comments I've quoted.
I apologize for not having anything directly productive to add to the issue at this point, but I want to add to the tone of the conversation about security in general: Make it secure by default and establish good practices, but I think it is wrong to take away choice completely.
Not being able to upload a file of any type to a generic file field is a bug in my eyes, and I feel like looking at it otherwise indicates to me that you are making your opinion from a stance of how to restrict users and prevent problems, rather than enabling them and promoting possibility. Personally, I'd rather Drupal be my car than my seat belt.
Security guidelines are generalizations after all, and they don't apply to every situation. Others before me have already stated perfectly adequate use cases to prove it in this instance.
I'm not expecting to have expressed any pivotal rationale that will sway the world here, but if I've made known the attitude of one other Drupal user out in the world then I've accomplished my goal.
Comment #49
JamesK CreditAttribution: JamesK commented#45: disallowed-extensions-997900-045.patch queued for re-testing.
Comment #51
JamesK CreditAttribution: JamesK commentedRe-roll.
Comment #52
JamesK CreditAttribution: JamesK commentedComment #53
attiks CreditAttribution: attiks commentedtrailing space
Comment #54
JamesK CreditAttribution: JamesK commentedThx. Still nr
Comment #55
JamesK CreditAttribution: JamesK commentedfixed trailing space, and a missing space
Comment #56
Gaelan CreditAttribution: Gaelan commentedJust to be clear, I want this feature too, but it can be dangerous! Imagine this sequence of events:
sites/default/files/foo.php
And no one wants that to happen! Although this is nice, be careful who can create that content type!
Comment #57
JamesK CreditAttribution: JamesK commentedAs discussed in this issue already, the default value is to be restrictive, it is up to administrators to lighten those restrictions as they choose. If they choose to allow PHP uploads, then we should expect that they've configured their HTTPd appropriately to block them executing. We should not force limitations on admins.
Comment #58
Gaelan CreditAttribution: Gaelan commented@JamesK I totally agree with you. I was just trying to clarify.
Comment #59
attiks CreditAttribution: attiks commentedI tested this using an unlimited file field, excluding txt extension
1/ upload test.xml - OK
2/ upload test.php gives two warnings
Comment #60
attiks CreditAttribution: attiks commentedReason: file_munge_filename is called with $extensions = 'txt' so the logic doesn't work anymore.
Comment #61
attiks CreditAttribution: attiks commentedSame goes for file_save_upload
Comment #62
JamesK CreditAttribution: JamesK commentedChanges in this patch:
Tagged as needs tests because we need coverage for using blacklists in all the functions that validate extensions. I'd like to get some agreement on this feature before spending the time writing them.
Comment #63
JamesK CreditAttribution: JamesK commentedComment #64
attiks CreditAttribution: attiks commentedisn't it easier to add the new parameter to the end?
Comment #65
attiks CreditAttribution: attiks commentedI did the same test as in #59
1/ I think we need some more information for the users on 1, so they now that php|pl|py|cgi|asp|js are always renamed
1/ Why do we need to add the .txt extension to those files, why not use .php_
3/ I expected this but is it desirable?
Edit: typos
Comment #67
JamesK CreditAttribution: JamesK commentedWell this isn't new behaviour to this issue. Files ending in php|pl|py|cgi|asp|js were always renamed before this patch. I just added the _ to make the behaviour the same as file_munge_filename (and thus make it compatible with file_unmunge_filename). If this is controversial, I'll split it into its own issue.
Comment #68
attiks CreditAttribution: attiks commentedI created a new issue for 67: #1540008: Allowed file extensions don't mention that some extensions need an override in settings.php
Comment #69
JamesK CreditAttribution: JamesK commentedThis patch fixes broken tests.
Re: #64: It is definitely easier, but it makes for an awkward ordering of arguments.
Comment #70
JamesK CreditAttribution: JamesK commentedComment #71
attiks CreditAttribution: attiks commented#69, true but is doesn't need an API change. tests are passing locally
what to do with:
1/ Why do we need to add the .txt extension to those files, why not use .php_
3/ I expected this but is it desirable?
Comment #72
JamesK CreditAttribution: JamesK commentedI don't know. We would need to dig out whatever issue that got committed in.
Comment #73
Gaelan CreditAttribution: Gaelan commented#72: This sounds like a job for
git blame
.Comment #74
attiks CreditAttribution: attiks commentedis always been like that and the same goes for
, this is needed for apache (according to the comments)
So only thing left is the order of the parameters, if we add it to the end this can be backported easily, if not I guess we cannot backport without breaking contrib?
Comment #75
JamesK CreditAttribution: JamesK commentedWell there is already a semi-solution in contrib for D7.
I'm OK with this being D8-only.Edit: This actually should be backportable. Do you think the awkward argument ordering is very important?Comment #76
attiks CreditAttribution: attiks commentedI have no idea, depends on how many contrib modules call function file_munge_filename
file_unmanaged_movedirectly, i'll try to find outComment #77
Alan D. CreditAttribution: Alan D. commentedLots! You should not rename / reorder this in D7
Comment #78
attiks CreditAttribution: attiks commented@Alan: you saw the eidt in #76, it's only file_munge_filename. If so any examples?
Comment #79
Alan D. CreditAttribution: Alan D. commentedSorry missed that. But for reference: Backport policy, particularly the points at the bottom.
[edit]
I have used this once on a Drupal 6 site. I can not think of any contrib modules that use it.
I would suggest, doing the D8 fix with the "awkward parameters", backport if the powers to be are happy with it, then introduce a separate D8 issue to clean this up. An API change usually means a much longer wait in the queues or (worst case) it never gets committed.
Comment #80
attiks CreditAttribution: attiks commentedI found 3 contrib modules (so far) using file_munge_filename, I'll assume there're more, so @JamesK i think we should go with the awkward argument ordering
http://drupalcode.org/project/video.git?a=search&h=HEAD&st=grep&s=file_m...
http://drupalcode.org/project/services.git?a=search&h=HEAD&st=grep&s=fil...
http://drupalcode.org/project/flashvideo.git?a=search&h=HEAD&st=grep&s=f...
patch attached with the new order
Comment #81
attiks CreditAttribution: attiks commentedFollow up created: #1540514: Re-order parameters of file_munge_filename
Comment #82
attiks CreditAttribution: attiks commentedI added 2 new tests to test the exclusion of extensions as well.
Comment #83
JamesK CreditAttribution: JamesK commentedThanks attiks, this is great.
I removed some whitespace, and renamed the parameter in file_validate_extensions.
Comment #85
JamesK CreditAttribution: JamesK commentedwoops
Comment #86
attiks CreditAttribution: attiks commentedremove white space from tests
Comment #87
AaronBaumantagging for (eventual) backport.
cross-linked to #803926: File field shouldn't allow any file extension to be uploaded when the list of allowed extensions is left blank
Comment #88
cweagansFixing tags per http://drupal.org/node/1517250
Comment #89
alekth CreditAttribution: alekth commented#85: disallowed-extensions-997900-85.patch queued for re-testing.
Comment #90
Sheldon Rampton CreditAttribution: Sheldon Rampton commentedI just want to throw in my opinion after wasting several hours of my time dealing with this, which is most certainly a bug in Drupal 7 and not just a new feature request. I have a client who expressly asked to be able to upload any file type on their website. For this client's website, that is a reasonable request. It doesn't create a security hole because only trusted personnel will have user accounts. Right now, Drupal 7 provides no way for me to accommodate that request. The allow_all_file_extensions module is helpful on other websites, but it doesn't work on the website I'm building, which uses the Media module and the file_entity module. After spending a few hours trying to understand how these various modules affect file extension validation, I've just given up and decided to simply hack the file_validate_extensions() function so it doesn't validate at all. I hate hacking Drupal core, but I also hate losing hours of my life trying to fix a problem that only exists because some over-officious people decided that they know better than me what my clients need or can be trusted to handle.
If someone cares to help me figure out how to meet my client's needs without hacking core, I'd love the advice. In the meantime, I just want to second the opinion of the guy who wrote that Drupal should "Make it secure by default and establish good practices, but I think it is wrong to take away choice completely." In fact, taking away choice completely is self-defeating, because it forces developers like me to adopt even worse practices such as hacking core, just so we can escape the prison that has been built for us.
Comment #91
attiks CreditAttribution: attiks commented#90: best way forward is to test the patch so it can be committed to D8 and backported to D7
Comment #92
Sheldon Rampton CreditAttribution: Sheldon Rampton commented@attiks: That sounds like a good suggestion. Unfortunately, I don't have time myself right now to test the patch in D8. I'll try to come back to this issue after I've met my client's immediate needs.
Comment #93
JamesK CreditAttribution: JamesK commented#86: i997900-86.patch queued for re-testing.
Comment #95
JamesK CreditAttribution: JamesK commentedI didn't really expect it to still apply. Anyway, #91 looks like we need yet another reroll first.
Comment #95.0
JamesK CreditAttribution: JamesK commentedremaining tasks
Comment #96
Stefan Lehmann CreditAttribution: Stefan Lehmann commentedI took over all the changes from #86 and applied them onto the current code base, but I think I'm lacking a bit experience. Especially the file.js has quite changed. I commented out the relevant part in the JS file, as it doesn't make sense anymore. The file upload on a node form breaks at the moment with my patch applied.
Can somebody else (more experienced) take it over from here?
Comment #97
superspring CreditAttribution: superspring commentedComment #99
thedavidmeister CreditAttribution: thedavidmeister commentedThis looks to me like a dupe of #838456: Ability to allow any extension in file uploads
Comment #100
thedavidmeister CreditAttribution: thedavidmeister commentednm, the approach here is obviously better and more work has been done here. Allowing the swap to a blacklist instead of a whitelist for file extensions totally makes sense.
Comment #101
thedavidmeister CreditAttribution: thedavidmeister commentedI'd like to say that I think if we're adding functionality to replace the file extension whitelist with a blacklist, we should have an equivalent "safe blacklist" that we provide by default containing known-unsafe file extensions (.exe, .php, etc..), otherwise the patch isn't much more palatable than #838456: Ability to allow any extension in file uploads.
Comment #106
AaronBaumanrerolled against latest
not sure if this needs bumped to 8.1.x or not
Comment #107
AaronBaumanRerolled once more to fix a number of failing issues:
- form state is now a classed object
- swap FileInterface for File
- swap getFilename() for filename
- change "Allowed types" help text to "Disallowed types" as applicable
Comment #114
ao2 CreditAttribution: ao2 as a volunteer commentedHi, is there still interest in this? BTW, the patch does not apply cleanly to 8.4
Comment #115
dbyers55 CreditAttribution: dbyers55 commentedI'm still very much interested in this.
Comment #116
OWastStill using the patch in D7. If client would finally get around to upgrading, this would be a requirement.
Comment #119
AaronBaumanReroll of #108 against 8.7.x
Comment #120
dwwAdding some relevant related issues:
#3021652: Deprecate upload-related functions file.inc and move to a file upload service will definitely conflict with this, since it's moving
file_munge_filename()
to a service.#2492171: Provide options to sanitize filenames (transliterate, lowercase, replace whitespace, etc) will also conflict with this, since it's making some changes to how we rename files inside
_file_save_upload_single()
Mostly just FYI. I have no idea what order or timeframe any of these patches might actually land in...
p.s. I feel partly responsible for this, since I helped make #803926: File field shouldn't allow any file extension to be uploaded when the list of allowed extensions is left blank happen in the first place. ;)
Comment #121
AaronBaumanThanks for the FYI, though not sure I have bandwidth to keep track of all those threads.
:shakes fists:
Comment #124
maticb CreditAttribution: maticb commentedI used the patch in #119 in combination with a custom file upload widget, and I keep getting this warning, the built in drupal validation fails on file.js line 86, because the file extensions I had to provide in my custom widget are no longer a string, but an array of string and boolean value, as I have to set it inthe default settings of my custom widget, to get rid of PHP warnings:
See screenshot for the warning:
Not sure if I did something wrong in my custom widget, I fixed it internally by patching core on my project, just wanted to point this out for further development of this issue.
Comment #126
alexpottNote that there are serious security concerns with doing this. It is completely against the recommendations of OWasp - see https://www.owasp.org/index.php/Unrestricted_File_Upload
Comment #127
dww+1000 to #126. I'd still love to "works as designed" this issue, instead of "fixing" it.
Comment #133
quietone CreditAttribution: quietone at PreviousNext commentedGot this from the bugsmash bingo.
I read the issue summary and then skimmed the comments. I do not see a bug here, this is more like a feature request. And It was pointed out that there are solutions in contrib. It is also informative that this issue opened in 2010 and was steadily discussed until May 2014, then it became very quiet here. Perhaps there is no longer interest in this change being in core? Most telling is the comment by alexpott in #126 referencing OWASP documentation explaining why something like this is not good practice. Therefor, I can't see this being made available in Drupal core.
So, changing to a feature request and closing as works as designed (per suggestion in #127).
As always, if you disagree, re-open the issue and comment on what still needs to be done.
Thanks!