You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dean Gaudet <dg...@arctic.org> on 1997/11/14 10:50:28 UTC

Re: general/1402: Relative Symlinks are handled improperly


On 14 Nov 1997 stig@hackvan.com wrote:

> Dean Gaudet wrote:
> > 
> > An idea just occured to me: a really cheap way to protect a root
> > filesystem from being served is to check st_dev in the stat structure and
> > only allow serving from particular devices.  Hmmm. 
> 
> Bing!  A fine idea!  Great.  Excellent.  This would help a great deal!

Try this module.  I'm running it now ... it will take a few tweaks to get
it to work with 1.2 though.  Probably just change the logging call and
delete a few structure elements from the module structure.

Dean

/*
 * mod_allowdev: prohibit files from being served unless they're
 * on a listed device.
 * 
 * Author: Dean Gaudet <dg...@arctic.org>
 */

/*
 * Usage: Go down there and hard code the list of devices from
 * which you allow content to be served.  Stick an appropriate
 * "AddModule modules/extra/mod_allowdev.o" directive at the
 * very bottom of your src/Configuration file, rebuild.
 */

/* TODO: Add a config directive "AllowDev" which takes a
 * filename, stats the file to find out what device it is on.
 * Fail gracefully, if the file doesn't exist, it's fine to
 * continue, you're not going to allow files to be served which
 * wouldn't otherwise be serveable.
 *
 * TODO: Device numbers should be easy to hash.
 */

#include "httpd.h"
#include "http_config.h"
#include "http_log.h"

/* don't ask why we run this in header_parse phase ... well ok,
 * go ahead, ask.  It's because there's no other way to protect
 * against the Satisfy directive.
 */
static int check_device(request_rec *r)
{
    if (r->finfo.st_mode == 0) {
	return DECLINED;
    }
    switch (r->finfo.st_dev) {
    /* hard code the list of acceptable devices here */
    case 0x0303:
    case 0x1602:
	return DECLINED;
    }
    aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
	"mod_allowdev: request to %s is on device 0x%x, forbidden",
	r->uri, r->finfo.st_dev);
    return HTTP_FORBIDDEN;
}


module MODULE_VAR_EXPORT allowdev_module =
{
    STANDARD_MODULE_STUFF,
    NULL,			/* initializer */
    NULL,			/* dir config creater */
    NULL,			/* dir merger --- default is to override */
    NULL,			/* server config */
    NULL,			/* merge server config */
    NULL,
    NULL,			/* handlers */
    NULL,			/* filename translation */
    NULL,			/* check_user_id */
    NULL,			/* check auth */
    NULL,			/* check access */
    NULL,			/* type_checker */
    NULL,			/* fixups */
    NULL,			/* logger */
    check_device,		/* header parser */
    NULL,			/* child_init */
    NULL,			/* child_exit */
    NULL			/* post read-request */
};


#if 0

/* If you don't know how to figure out the device number, just compile
 * this program, and run it with a list of files, one per device
 * you're interested in.  It'll stat them and tell you their device
 * numbers.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

void main(int argc, char **argv)
{
    struct stat buf;

    while (++argv, --argc) {
	if (stat (argv[0], &buf) == -1) {
	    fprintf(stderr, "stat(%s) error: %s\n", argv[0], strerror(errno));
	    continue;
	}
	printf("0x%x\t%s\n", buf.st_dev, argv[0]);
    }
    exit(0);
}
#endif



Re: general/1402: Relative Symlinks are handled improperly

Posted by Dean Gaudet <dg...@arctic.org>.

On Fri, 14 Nov 1997, Dean Gaudet wrote:

> On 14 Nov 1997 stig@hackvan.com wrote:
> 
> > Dean Gaudet wrote:
> > > 
> > > An idea just occured to me: a really cheap way to protect a root
> > > filesystem from being served is to check st_dev in the stat structure and
> > > only allow serving from particular devices.  Hmmm. 
> > 
> > Bing!  A fine idea!  Great.  Excellent.  This would help a great deal!
> 
> Try this module.  I'm running it now ... it will take a few tweaks to get
> it to work with 1.2 though.  Probably just change the logging call and
> delete a few structure elements from the module structure.

Ack, here's v0.02.  header_parse is the wrong phase to use, because it's
not run by subrequests.  So for example:

% ln -s /etc/passwd pwhack
% echo '<!--#include file="pwhack"-->' >pw.shtml

would be able to include /etc/passwd. 

This is fixed by using the fixup phase instead.

Dean

/*
 * mod_allowdev: prohibit files from being served unless they're
 * on a listed device.  v0.02.
 * 
 * Author: Dean Gaudet <dg...@arctic.org>
 */

/*
 * Usage: Go down there and hard code the list of devices from
 * which you allow content to be served.  Stick an appropriate
 * "AddModule modules/extra/mod_allowdev.o" directive at the
 * very bottom of your src/Configuration file, rebuild.
 */

/* TODO: Add a config directive "AllowDev" which takes a
 * filename, stats the file to find out what device it is on.
 * Fail gracefully, if the file doesn't exist, it's fine to
 * continue, you're not going to allow files to be served which
 * wouldn't otherwise be serveable.
 *
 * TODO: Device numbers should be easy to hash.
 */

#include "httpd.h"
#include "http_config.h"
#include "http_log.h"

/* This runs as a fixup because we don't want it to be affected
 * by any "Satisfy" directive.  It must always be satisfied.
 * fixups happen to also be run for all requests and subrequests.
 */
static int check_device(request_rec *r)
{
    if (r->finfo.st_mode == 0) {
	return DECLINED;
    }
    switch (r->finfo.st_dev) {
    /* Hard code the list of acceptable devices here, don't worry
     * about the "DECLINED" that's just the way of saying "this
     * module doesn't have any reason to stop this request".
     */
    case 0x0303:
    case 0x1602:
	return DECLINED;
    }
    aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
	"mod_allowdev: request to %s is on device 0x%x, forbidden",
	r->uri, r->finfo.st_dev);
    return HTTP_FORBIDDEN;
}


module MODULE_VAR_EXPORT allowdev_module =
{
    STANDARD_MODULE_STUFF,
    NULL,			/* initializer */
    NULL,			/* dir config creater */
    NULL,			/* dir merger --- default is to override */
    NULL,			/* server config */
    NULL,			/* merge server config */
    NULL,
    NULL,			/* handlers */
    NULL,			/* filename translation */
    NULL,			/* check_user_id */
    NULL,			/* check auth */
    NULL,			/* check access */
    NULL,			/* type_checker */
    check_device,		/* fixups */
    NULL,			/* logger */
    NULL,			/* header parser */
    NULL,			/* child_init */
    NULL,			/* child_exit */
    NULL			/* post read-request */
};


#if 0

/* If you don't know how to figure out the device number, just compile
 * this program, and run it with a list of files, one per device
 * you're interested in.  It'll stat them and tell you their device
 * numbers.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

void main(int argc, char **argv)
{
    struct stat buf;

    while (++argv, --argc) {
	if (stat (argv[0], &buf) == -1) {
	    fprintf(stderr, "stat(%s) error: %s\n", argv[0], strerror(errno));
	    continue;
	}
	printf("0x%x\t%s\n", buf.st_dev, argv[0]);
    }
    exit(0);
}
#endif