SecureAttachments

Summary: Security issues for attachments
Version: n/a
Prerequisites: Requires at least PmWiki version: 2 beta 31
Status:
Maintainer:

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?

Answer

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).

  1. Protect the uploads directory by either of the following three methods:
    • putting it in a location on the server which is not publicly accessible, i.e. outside the html/ or html_public/ directory ($UploadDir = '/path/to/uploads';).
    • configure the webserver to block all requests to files in the uploads/ directory. For Apache servers this can be done by changing httpd.conf; for other webservers consult its appropriate documentation.
    • if the server is running Apache, add a .htaccess file to the upload directory with content
      Order Deny,Allow
      Deny from all
    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.)
  2. 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 http://mysite.com/pmwiki/pmwiki.php?n=SomeGroup.SomePage&action=download&upname=filename.ext.
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.

Secure Downloads

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' 
      $PageAttributes['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 http://www.pmwiki.org/wiki/Cookbook/GeminiSkin?action=download&upname=gemini.zip

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:

  1. Step 1 as above.
  2. 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]
  1. Add the following to your PmWiki config file (adjust as appropriate):
$UploadUrlFmt = '/attach';

--EemeliAro February 06, 2008

See Also

Contributors

HansB

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.