Summary: Security issues for attachments
Prerequisites: Requires at least PmWiki version: 2 beta 31
Questions answered by this recipe
How do I protect page and group attachments when the page or group is read-protected by a password?
How do I safeguard attachments from public access?
How do I enable attachments when the webserver disallows direct access to files that have been created
by a PHP script?
You need to protect the files in the uploads directory from public access (step 1) and change PmWiki's default mechanism of using the
Attach:filename.ext markup so it can access the protected files (step 2).
- Protect the uploads directory by either of the following three methods:
If you wish to protect only files in a specific group SomeGroup, you can put such a .htaccess file in the uploads/SomeGroup/ directory and set
$EnableDirectDownload = 0;
for that group only (next step).
(There are copies of this file available in local/ and wiki.d/ that can be simply copied into uploads/ . This way the uploads/ directory can stay in the same location as the other PmWiki files.)
- Change Pmwiki's mechanism to handle attachments by setting in local/config.php, or local/SomeGroup.php for group SomeGroup:
$EnableDirectDownload = 0;
This will disable pmwiki's default mechanism of converting the
Attach:filename.ext markup to a url pointing directly to the file, like
http://mysite.com/pmwiki/uploads/SomeGroup/filename.ext, and uses ?action=download instead, like
Thereby the standard page or group password protection applies to the attachments as well.
Note about security
In case of the default per-group uploads directory structure (see UploadGroups and
$UploadPrefixFmt), an attachement is as "secure" as the lowest level of protection any page in the group: if the group has non-protected pages, the attached file could possibly be downloaded without a password (discussion). If the uploads are saved "per-page", then the attachment is protected by the password of the page.
To have secure downloads you can set a download-password (see PasswordsAdmin, section: Protecting actions). Include the following in config.php:
$EnableDirectDownload = 0; # Use PmWiki's download mechanism
$HandleAuth['download'] ='download'; # Tell PmWiki that the 'download' password allows action 'download'
$DefaultPasswords['download'] = ''; # Clear the default password for 'download'
"$['Set new download password']"; # Add a new field to the attr page
With this you can set a group wide download passwort in the GroupAttributes page. This method works better than setting the variable
$EnableUploadGroupAuth = 1, because read and download passwords are separated. A visitor can see all the PmWiki Pages in a group, but to download an attachment he must be authenticated.
Notes and Comments
(from the pmwiki-users list:)
By default when PmWiki generates "Attach:" links, it creates them as "direct" links into the webserver directory. For example, in the Cookbook the markup "
Attach:gemini.zip" is converted to a link to http://www.pmwiki.org/pmwiki/uploads/Cookbook/gemini.zip.
Note that when followed this link will completely bypass the pmwiki.php script, and act as though you were accessing any "normal" file on the webserver.
This has some advantages and disadvantages. The biggest advantage is that it's fast, in that the webserver doesn't have to execute a PHP script in order to return the appropriate file to the browser. The
webserver can also take care of determining the appropriate Content-Type for the file.
However, a big disadvantage is that all attachments are publicly accessible as long as someone knows the URL. In addition, there are some environments (examples include IIS and sourceforge.net) where the webserver disallows direct access to files that have been created by a PHP script.
As a result, beta31 now offers an ?action=download option, which can be used to retrieve a page's attachment. For example, with
$EnableDirectDownload set to zero, PmWiki will convert the "
Attach:gemini.zip" markup into
This provides some important features:
- it allows PmWiki to use site/group/page permissions to control access to attachments
- it means the uploads/ directory no longer needs to be web accessible and can be anywhere in the filesystem
- the file's Content-Type and semantics can be controlled by PmWiki which may be easier to configure (e.g., it makes it easier for .php attachments to be downloaded instead of executed on the server)
Of course, the downside of this is that accessing an attachment a somewhat heavier load on the server, since it now involves running a PHP script and determining the page's permissions before the file can be transmitted.
Still, for sites that want to use PmWiki's authorization system to restrict access to attachments, or that are on webservers that disallow accessing the attachments directly, this is an incredibly useful feature and the trade-offs in performance isn't important. --Pm
If you want to handle attachments using PmWiki access control but would also like to have clean URLs for your uploads, this is possible using Apache's mod_rewrite (see Cookbook.CleanUrls for more info). To achieve this, do as follows:
- Step 1 as above.
- Don't disable
$EnableDirectDownload. Instead, add something like the following to your Apache .htaccess or other config file (change the 'attach' to whatever you want that doesn't clash with your existing files & directories):
RewriteRule ^attach/(.+)/([^/]+)$ path/to/pmwiki.php?n=$1&action=download&upname=$2 [QSA,L]
- Add the following to your PmWiki config file (adjust as appropriate):
$UploadUrlFmt = '/attach';
--EemeliAro February 06, 2008
User notes +2: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.