Page 1 of 1

HTTP Headers input

Posted: Mon Jul 14, 2008 4:25 pm
by tecktalkcm0391
Hello, I know that you need to validate any user supplied data, including HTTP Headers... so how could I secure this:

Code: Select all

    var $page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // Requested page
 
It's for a cache creating class... if you need more of the code, just let me know.

Thanks,
Chris

Re: HTTP Headers input

Posted: Mon Jul 14, 2008 5:25 pm
by Oren
Well it depends on how and what you gonna do with $page.

Re: HTTP Headers input

Posted: Mon Jul 14, 2008 6:35 pm
by tecktalkcm0391
cache the file with the following:

Code: Select all

 
    // Settings
    var $cachedir = YB_ROOT_S.'public/cache/'; // Directory to cache files in (keep outside web root)
    var $cachetime = 600; // Seconds to cache files for
    var $cacheext = 'cache'; // Extension to give cached files (usually cache, htm, txt)
    // Script Vars
    var $page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // Requested page
    var $cachefile = $this->cachedir . md5($page) . '.' . $this->cacheext; // Cache file to either load or create
    // Defaults - DO NOT EDIT
    var $ignore_page = false;
    var $started = true; 
    var $cachefile;
    
    // Ignore List
    var $add_list = array(
        '*.com/rss.php',
        '*.com/search/'
    );
     
    function start(){
 
        for ($i = 0; $i < count($this->add_list); $i++) {
            $add_list = (strpos($this->page, $this->add_list[$i]) !== false) ? true : $this->add_list;
        }
         
        $cachefile_created = ((@file_exists($this->cachefile)) and ($this->add_list === false)) 
                                ? @filemtime($this->cachefile) : 0;
        @clearstatcache();
         
        // Show file from cache if still valid
        if (time() - $this->cachetime < $cachefile_created) {
         
        //ob_start('ob_gzhandler');
        @readfile($cachefile);
        //ob_end_flush();
        exit();
         
        }
         
        // we need to generate a cache file
         
        ob_start();
    }
 

Re: HTTP Headers input

Posted: Mon Jul 14, 2008 6:35 pm
by tecktalkcm0391
tecktalkcm0391 wrote:cache the file with the following:

Code: Select all

 
    // Settings
    var $cachedir = YB_ROOT_S.'public/cache/'; // Directory to cache files in (keep outside web root)
    var $cachetime = 600; // Seconds to cache files for
    var $cacheext = 'cache'; // Extension to give cached files (usually cache, htm, txt)
    // Script Vars
    var $page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // Requested page
    var $cachefile = $this->cachedir . md5($page) . '.' . $this->cacheext; // Cache file to either load or create
    // Defaults - DO NOT EDIT
    var $ignore_page = false;
    var $started = true; 
    var $cachefile;
    
    // Ignore List
    var $add_list = array(
        '*.com/rss.php',
        '*.com/search/'
    );
     
    function start(){
 
        for ($i = 0; $i < count($this->add_list); $i++) {
            $add_list = (strpos($this->page, $this->add_list[$i]) !== false) ? true : $this->add_list;
        }
         
        $cachefile_created = ((@file_exists($this->cachefile)) and ($this->add_list === false)) 
                                ? @filemtime($this->cachefile) : 0;
        @clearstatcache();
         
        // Show file from cache if still valid
        if (time() - $this->cachetime < $cachefile_created) {
         
        //ob_start('ob_gzhandler');
        @readfile($cachefile);
        //ob_end_flush();
        exit();
         
        }
         
        // we need to generate a cache file
         
        ob_start();
    }
 
    function finish(){
        // Now the script has run, generate a new cache file
        $fp = @fopen($this->cachefile, 'w');
         
        // save the contents of output buffer to the file
        @fwrite($fp, ob_get_contents());
        @fclose($fp);
         
        ob_end_flush(); 
    }
 

Re: HTTP Headers input

Posted: Tue Jul 15, 2008 6:56 am
by Oren
You can save whatever you want to a file - if you are not using it later anywhere then why should you care? but I guess it's not the case, if you cache it then you are going to use it somewhere in one way or another and that's what matters. Tell us what exactly you gonna do with it and where you gonna use it, not how you process it and save it. Anyway, I don't see how this is a new security issue... why do you think it is different than any other security issues that you deal with when, for example, you save a user reply to a blog post?
Of course if you save it to a database, then you'll have to take care for SQL injections as well... that's why I said that it depends what exactly you do with it and where exactly you gonna use it.

Re: HTTP Headers input

Posted: Tue Jul 15, 2008 2:29 pm
by Mordred
Step 1.
To check if it's used safely, first follow the instances where it is used:
1. md5($page) --> safe, md5() can eat anything.
2. strpos($this->page,...) -> safe, strpos can eat anything too.
3. If we were paranoid, we would check how these string functions behave with huge string. As we're dealing with URLs, which have a limited lenght, it's probably safe. If we were trully paranoid, we would check anyway ;)
4. If at any point the value is assigned to another variable, follow that one as well.

Step 2.
To check if it's used correctly, follow the instances again:
1. You use md5() to "compess" the URL in the cache filename. URLs are not regular strings though.

Code: Select all

index.php?a=b&c=d
index.php?c=d&a=b
These are different strings, but the same URL. This may lead to cache misses, and can be used to exhaust cache resources, even if you check the validity of the URL. An URL with N parameters can be written in N! (N-factorial) ways, which will md5() to different cache names, even though they are the same URL.

2. strpos(...) -- this logic is not working, and it has never worked as it is written. Now let's suppose it is working. URLs are not regular strings, remember? Substring matching is not the correct way to handle this logic.
blabla.php?a=b&c=d&dummy=foo.com/rss.php will happily match, even though it's not what you had in mind.
So the attacker also has a way to stop the caching mechanism. He may choose a "heavy" page, pad the URL with a dummy value, and then post it on slashdot, so that the failed caching will DOS the server.