hi everybody,
on drupal 4.6.0 with image.module, you can reach every file you want by typing something like :

http://yoursite/system/files?file=../path/to/file

for ex. you cand download this :

http://yoursite/system/files?file=../sites/default/settings.php

look at my screenshot.

i hope that someone had just fixed this before, but i didn't find it.

if not..... beware!
that's a security big bug! :-(

CommentFileSizeAuthor
sshot.jpg35.5 KBtexaskills

Comments

jhriggs’s picture

This does not seem to be a bug with Drupal or with image.module. Do you have some other file-handling module installed that may be doing this? Or is it caused by your web server setup? I just get a 404 (page not found) when I try this.

texaskills’s picture

ouch!
you are right!

i think this is a drupal bug, because i have no special configs on my web server (apache 1.3.33 on slackware 10.0)

which file is called when i go to:

system/files?

perhaps some drupal module ?

pegmonkey’s picture

sounds like apache. Either file system permissions, or allow directory listing is enabled. JMHO.. I get 403 forbidden when I try it.

texaskills’s picture

oh! i use mod_rewrite

maybe you get 404 if you don't use it (i guess)

jhriggs’s picture

No, I'm using clean URLs and mod_rewrite. system/files is handled by system.module. The callback is file_download in file.inc. There must be some module enabled that is allowing access to that file. Try this from your drupal directory (assuming you are using some *nix flavor):

grep -rl _file_download modules/

This will give you a list of all of the modules that implement the file_download hook. Try disabling them one at a time until you can no longer download "secret" files. I already tried image, flexinode, project, and upload. None of them seems to be the culprit. Do you get other results?

texaskills’s picture

hi,
it can't be Options Indexes, i have Options -Indexes on my virtualhost .htaccess.
i think it can't be neither filesystem problems because i still remain on the drupal wwwroot.
and if i use or not mod_rewrite i can download php file sof my site :-/

texaskills’s picture

hi,
yes i'm on linux :-)

i got this

modules/flexinode/flexinode.module
modules/upload.module
modules/user.module

and after have disabled flexinode i can't get any file via file system.
damned buggyflexi :-/

pegmonkey’s picture

I stand corrected.. I can get to some files that way...

texaskills’s picture

can you?
:-)

so, lets' go to the flexinode issue archive :-)

thanks for the help! :-)

walkah’s picture

Project: Image » Drupal core
Version: 4.6.x-1.x-dev » 4.6.0
Component: image.module » file system

this is a 'file.inc' issue, not specific to image.module... re-assigning and will look into it further.

pegmonkey’s picture

Project: Drupal core » Image
Version: 4.6.0 » 4.6.x-1.x-dev
Component: file system » image.module

yep, it was flexinode for me too.. Thanks for pointing that out. :)

pegmonkey’s picture

Project: Image » Drupal core
Version: 4.6.x-1.x-dev » 4.6.0
Component: image.module » file system
texaskills’s picture

on includes/file.inc, line 454 :

function file_download() {
$file = $_GET['file'];
if (file_exists(file_create_path($file))) {
$list = module_list();
foreach ($list as $module) {
$headers = module_invoke($module, 'file_download', $file);
if ($headers === -1) {
drupal_access_denied();
}
elseif (is_array($headers)) {
file_transfer($file, $headers);
}
}
}
drupal_not_found();
}

this is the line, i think, to change, IMHO:

if ($headers === -1) // because there is no verification on file extension neither file path

but i'm not able to do it :-)

texaskills’s picture

ok, try this:

file: includes/file.inc
line: 454

function file_download() {
$file = $_GET['file'];
if (file_exists(file_create_path($file))) {
$list = module_list();
foreach ($list as $module) {
$headers = module_invoke($module, 'file_download', $file);
if ($headers === -1) {
drupal_access_denied();
}
elseif (is_array($headers)) {
$file_ext_regex = "^(.*)(php|inc)$";
if ( eregi($file_ext_regex,$file) ) {
@header("Location: /");
exit;
}
file_transfer($file, $headers);
}
}
}
drupal_not_found();
}

just insert this:

$file_ext_regex = "^(.*)(php|inc)$";
if ( eregi($file_ext_regex,$file) ) {
@header("Location: /");
exit;
}

on line 464.
add every file extension you want with (php|inc|some|thing|you|want|to|deny)

i hope will work for everyone.

pegmonkey’s picture

That works for me. Many thanks.

texaskills’s picture

great :-)

i wonder if there will be some more security options to configure via drupal in the near future :-)

bye

texaskills’s picture

little funny solution:

replace with this the line wih "header..."

@header("Location: " .$base_url. "/error404");

--
tk

Cvbge’s picture

Priority: Normal » Critical
Cvbge’s picture

And sent mail so security@

chx’s picture

Thanks for contacting the Security Team! Next time please start with that.

While private file download is not the finest part of Drupal, it's not vulnerable.

We identified the problem being flexinode related and contacted the module maintainer and suggested a fix which he accepted.

Please upgrade your flexinode.

Anonymous’s picture