It's tough to know if this is more related to content_access or drupal core but will try here first.

When using content access to restrict node access, private file attachments are still downloadable. This is due to there being no check in place to see if the current user has access to the node that a file is attached to. As I needed this quickly, I created a light module which does just this. It's not the most elegant as going from FID to NID is not the easiest process.

It would make sense for this to be included with the content_access module.

All that needs to be done is work with the hook_file_download which is called when dealing with private files. Included below is the code I created for handling this. It assumes that a FID is only attached to one node.

/**
 * Implmentation of hook_file_download();
 */
function modulename_file_download($uri)
{  
  //get the current file's fid to work with
  $result = db_select('file_managed', 'c')
    ->fields('c')
    ->condition('uri', $uri)
    ->execute()
    ->fetchAssoc();

  //only proceed if the URI produced results
  if(count($result))
  {
    //Get the FID to be used later
    $fid = $result['fid'];

    //Loop through all possible fields
    foreach(field_info_field_by_ids() as $id => $field)
    {   
      //only act on fields of type file
      if($field['type'] == 'file')
      {   
        //only act on file fields that are set to private
        if($field['settings']['uri_scheme'] == 'private')
        {   
          //column name of the FID in the field's table
          $column = $field['field_name'].'_fid';

          //main table data
          $table_name = 'field_data_'.$field['field_name'];

          $results = db_select($table_name, 'c')
            ->fields('c')
            ->condition($column, $fid)
            ->execute()
            ->fetchAssoc();
                
          //only proceed if a node match was found
          if(count($results))
          {   
            //use the entity_id as it's the actual NID
            $nid = $results['entity_id'];
            $node = node_load($nid);

            if(node_access('view', $node))
            {   
              return array(
                'Content-Type' => $file->filemime, 
                'Content-Length' => $file->filesize,
              );  
            }   
            else
            {   
              return -1; 
            }   
          }   
        }   
      }   
    }   
  }
}

More than willing to answer questions if anything isn't clear or if help is needed implementing this.

Cheers.

Grant

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Akaoni’s picture

This is more related to drupal core and has been fixed in Drupal 7.1 (and hence Drupal 7.2).

See Access bypass in File module:
http://drupal.org/node/1168756

Akaoni’s picture

Status: Active » Closed (works as designed)
bblancha’s picture

I submit tht the Drupal core fix solves the problem for registered vs unregistered visitors. It does not however extend the fine node access capability of Content_Access to the file system. So for instance a node available only to a specified group which has file attachments will still allow those file attachements to be accessed by registered users who are not members of the group.
So, I also vote for enhancing content_access to extend the access control to file attachments of the node.

Akaoni’s picture

Sorry bblancha, didn't see your post as this issue's closed.

Pretty sure Content Access does this already. ??
If not, create a new feature request. ; )

alexkb’s picture

Status: Closed (works as designed) » Active

Hope it's ok, but I've tried to re-open the status of this bug, as it's still an issue, and shouldn't really be considered a feature request, as content_access is suppose to restrict access to content as the name suggests.

I've just tested Grant's module in 7.22 with content_access 7.x-1.2-beta1 and it works great. Nice work Grant!

greggles’s picture

Thanks for your bug report and for helping make this a better module. Could you provide this as a patch?

grantlucas’s picture

Status: Active » Postponed (maintainer needs more info)

From some tests on the site that was originally seeing this issue, I can no longer access files belonging to nodes which are denied to anonymous users (ie: issue is fixed).

Alexkb, what are the conditions in which you are able to access restricted files? I would like to see if I can reproduce it as well.

Thanks.

jalane81’s picture

Category: bug » support

I'm having the same problem with my site. I see the code up above and some talk about adding it to the core and it fixes it..

being that I'm a NOOB to Drupal Development, can someone give me a bit more detail on how to go about getting this code into my site, what file to create or edit, what directory to drop it in, etc?

Thank you

- Jason

carlnewton’s picture

I know this is very old, but I needed this code and the last question has gone unanswered.

Thanks for the code, Grant. Hopefully this will be put into the module eventually.

jalane81, to install this code as a module go to the /sites/all/modules/ directory and create /capatch

Within /capatch, create capatch.info with the following contents:

name = Content access patch
description = How ever you want to describe it
package = Custom development
core = 7.x
files[] = capatch.module

Then create capatch.module with the code above in it. Enable the newly created module.

carlnewton’s picture

Additionally, when using the code above, immediately after downloading a file, the next node to be loaded springs up the following error:

Notice: Undefined variable: file in capatch_file_download() (line 51 of /var/www/site/sites/all/modules/capatch/capatch.module).

I've added an isset conditional:


if(node_access('view', $node))
            {
              if (isset($file)) {
              return array(
                'Content-Type' => $file->filemime,
                'Content-Length' => $file->filesize,
              );  
              }
            }

carlnewton’s picture

Issue summary: View changes
FileSize
991 bytes
1.35 KB

I needed this to be quickly accessible in a module format so figured I'd supply for easy installation for you guys. Drupal.org has renamed the tar.gz for security reasons, so you'll have to rename. The code is pretty much exactly as grantlucas provided, except with my fix in post #10.

DaPooch’s picture

This code is a good idea but I've found it to be problematic in two ways:

1. It doesn't account for images that may also be private and the module as is will render all private images inaccessible, or at least the ones shared with a node that may also have a private file attached to it.

2. It doesn't really account for the use case where a file can be attached to multiple nodes, some restricting access and others that don't. By default I believe it will default to restrict if any node has restricted access but I haven't fully tested this scenario. The problem really is if multiple nodes use the same file there's no easy way of knowing which one is placing the restriction on it.

davidpugh’s picture

Hello, I am having the same issue.
files in the private file system associated with content types that are not accessible by anonymous users (because that content type is restricted by content access) can be viewed by an anonymous user if the user knows the url of the file in the private file structure.

I'm using Drupal version 7.52, and content access 7.x-1.2-beta2.
I downloaded this module created by grantlucas and installed it.
It now restricts all private files from being viewed, even files in the private file structure that are associated with nodes that are viewable by anonymous.

I debugged with devel debug log module and found that the $file variable is always showing up as null.

ie:

if (isset($file)) {.....}

*The $file variable above is always null.
$file is not defined anywhere.

Any idea why this would be?

Isostar’s picture

Category: Support request » Bug report
Priority: Major » Critical
Status: Postponed (maintainer needs more info) » Active

The content access module can even make files downloadable of nodes that were even not viewable without the module.
Examples:
- if permission 'view published content' is unchecked for anonymous users
- if an node is unpublished

In both cases the private files of the node are downloadable after activating the content access module (and rebuilding permissions)

Isostar’s picture

Issue tags: +Security
Sherif Darwish’s picture

Hi,

I tested the content access module and i still see this problem as critical one impacting one of my projects, if a file is marked as private and we do not have content access module installed then drupal will not allow access to this file. however after i installed the content access module i am able to access private files attached to nodes without any validation (i.e. anonymous users are able to access the files using its private url : http://domain.com/system/files/36479_0.m4a )

I tried going through content access module to check how the permissions are granted or denied for file access but it is taking me some time so i found this hook hook_file_download_access which can prevent access to file download based on user permission to the node where this file is attached

I tried it on my side and it worked this way, so when a private file is being downloaded drupal will check the user access to its parent node

I am not sure if this is the best way but i am open to enhance it or commit it to content access module

<?php
function mymodule_file_download_access($file_item, $entity_type, $entity) {
	global $user;
    // watchdog('mymodule', 'Entity: <pre>@$entity</pre>', array('@$entity' => print_r($entity, TRUE)), WATCHDOG_DEBUG);
	if ($entity_type == 'node') {
		return node_access('view', $entity);
	}
}
	
?>
wipeout_dude’s picture

Can anyone confirm if this bug is still present in the D8 version of the module?

markusa’s picture

Ping on this issue. Hard to see how this issue is not taken seriously....With 0 maintainer attention to this, makes one wonder what other problems lurking...

Is this the case for the D8 version?

cestmoi’s picture

I confirm it's the case for the D8 version too !!!

zkrebs’s picture

I'm considering this module for selling access through Drupal Commerce/Rules, but can't use it if there's a glaring security bug (we have private files on our site).

joshuasosa’s picture

How does this issue get replicated?

  1. On simplytest.me, I installed a new Drupal 7 instance with content_access-7.x-1.2-beta2
  2. In File system, I added a private file system folder called 'private'.
  3. In Basic page content type Manage Fields, I added a File field that uploads using the private file system.
  4. In Basic page content type Access Control, I unchecked anonymous from "View any page content" and "View own page content".
  5. I created a new Basic page and uploaded a file using the file field.

I can view the node while logged in, and get access denied while logged out. I can download the file while logged in using the /system/files URL that's automatically added to the page, but get access denied when attempting to visit that file URL while logged out.

I tried with per-node access settings, making Basic page viewable by anonymous but unchecking anonymous from my specific node, and get the expected result. I also tried not unchecking the "view own page" for anonymous, but still get access denied for anonymous.

capysara’s picture

I can’t recreate this either.
For anonymous users:

  1. Fresh D7 install
  2. Go to /admin/config/media/file-system and create Private file system path: sites/default/files/private
  3. Enable content_access-7.x-1.2-beta2
  4. To basic page content type, add file field with Upload destination: Private files
  5. Add basic page node with a private file
  6. Without changing content access config, private file is downloadable for anon users
  7. Access Control: uncheck anon from View any page content & View own page content
  8. I get access denied for both the node page and the direct link to the file (expected)

I also tried with access control for authenticated users of different roles:

  1. Create a new role
  2. Access Control: New role does not have View any/own page content (by default)
  3. Give a user the New Role
  4. Rebuild permissions & clear cache (just in case)
  5. The user with the New Role can access both the node and file (expected because authenticated users still have access, by default)
  6. Access Control: Remove View any/own page content access from auth user
  7. I get access denied for both the node page and the direct link to the file (expected)
  8. Access Control: give New Role View any/own page content
  9. The user with the New Role can access both the node and file
  10. Change to another authenticated user who does not have the New Role
  11. Access Control: authenticated users still do not have access to View any/own page content
  12. I get access denied for both the node page and the direct link to the file (expected)
presleyd’s picture

I can't reproduce this in D7 or D8 version. My attempts are the same as #22.

In addition, I tried the option listed in #14

  1. Fresh install of D7 or D8
  2. Setup private files
  3. Remove the 'view published content' permission from anonyous users
  4. Create a content type that has a file field that uses private files for storage
  5. Create new node of that content type with an attached file
  6. The node and file is viewable for authenticated users, neither is accessible for anonymous users (as expected)
  7. Install content access
  8. The node and file access is the same as 6 above
mkindred’s picture

I cannot reproduce this in D7.

Steps:

  1. Install fresh D7
  2. Configure private directory for files
  3. Define file field in 'page' content type, private
  4. Create new node with private file PDF
  5. Test as anonymous:
    1. Node: can view
    2. File: can view
  6. Install content_access
  7. Rebuild permissions
  8. Remove anonymous 'View any page content' and 'View own page content' permissions for 'page' content type
  9. Tested viewing as anonymous:
    1. Node: Access denied
    2. File: Access denied
gisle’s picture

Assigned: Unassigned » gisle
Status: Active » Fixed
Issue tags: -Security

I am unable to reproduce this in any of the project's supported versions.

Below is a fairly detailed description of how I've tested both branches.

Branch 7.x-1.x-dev:

  1. Set up private files in the GUI.
  2. Create a new custom content type named "with attachment" using the GUI.
  3. Add an attachment field for file attachments to this content type.
  4. Set upload destination to "Private files".
  5. Create content instance of "with attachment" with a file attacment.
  6. Visit node, and record attachment URL.
  7. Install and enable Content Access 7.x-1.x-dev.
  8. Permission rebuild requested: Rebuild permissions.
  9. Make sure anonymous has permission "View published content".
  10. Got to access control tab of "with attachment" and set permissions "View any with_attachment content" and "View own with_attachment content" for anonymous.
  11. Visit node as anonymous: Access granted
  12. Visit attachment URL as anonymous: Access granted.
  13. Got to access tab of "with attachment" and remove permissions "View any with_attachment content" and "View own with_attachment content" for anonymous.
  14. Rebuild permissions.
  15. Visit node as anonymous: Access denied.
  16. Visit attachment URL as anonymous: Access denied.

Branch 8.x-1.x-dev:

  1. Edit settings.php to have private files.
  2. Create a new custom content type named "with attachment" using the GUI.
  3. Add an attacment field for file attachments to this content type.
  4. Set upload destination to "Private files".
  5. Create content instance of "with attachment" with a file attacment.
  6. Visit node, and record attachment URL.
  7. Install Content Access 8.x-1.x-dev.
  8. Visit Home » Administration » Structure » Content types
  9. Permission rebuild requested: Rebuild permissions.
  10. Make sure anonymous has permission "View published content".
  11. Got to access control tab of "with attachment" and set permissions "View any with_attachment content" and "View own with_attachment content" for anonymous.
  12. Visit node as anonymous: Access granted
  13. Visit attachment URL as anonymous: Access granted.
  14. Got to access tab of "with attachment" and remove permissions "View any with_attachment content" and "View own with_attachment content" for anonymous.
  15. Visit node as anonymous: Access denied.
  16. Visit attachment URL as anonymous: Access denied.

My testing confirms what is reported by the four latest comments:

  • #21 - joshuasosa
  • #22 - capysara
  • #23 - presleyd
  • #24 - mkindred

The original report is from 2011 and I believe this has been fixed somewhere along the road from there, and that no patch is needed to fix this at this point.

I am moving to "Fixed" now. If someone disagree and still think this is an issue, please provide a detailed description of how to reproduce from a clean install. I'll continue to monitor this issue and will reopen if somebody produces evidence that this is still an open issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.