Medium .htaccess protection

From D3xt3r01.tk
Jump to navigationJump to search

WHY

Because I wanted to give some access to sime files based on some stuff ..

HOW

This will allow users with the user-agents starting with "Thing", "Some" and "Browser" to directly access files with extensions ".ex3", ".ex2" and ".ex1" without needing a password... it's useful for example on tablets where the players don't/can't auth...

AuthType Basic
AuthName "Restricted Files"
AuthUserFile /path/to/.passwords
AuthGroupFile /path/to/.groups
SetEnvIf User-Agent ^Thing isplayer=1
SetEnvIf User-Agent ^Some isplayer=1
SetEnvIf User-Agent ^Browser isplayer=1
SetEnvIf Request_URI "\.ex3$" isfile=1
SetEnvIf Request_URI "\.ex2$" isfile=1
SetEnvIf Request_URI "\.ex1$" isfile=1
<RequireAny>
    Require group onegroup anothergroup
    <RequireAll>
        Require env isfile
        Require env isplayer
    </RequireAll>
</RequireAny

MEDIUM2 WAY

You can do it somehow in another way .. you can make a page "auth.php" that would use sqlite to have a database user/ip/date ..

<?php
if(!isset($_SERVER['REMOTE_ADDR'])){
        $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
}
if(!isset($_SERVER['REMOTE_USER'])){
        $_SERVER['REMOTE_USER'] = 'cli';
}
$db = new PDO('sqlite:/tmp/sqlite.db');
$query = 'CREATE TABLE IF NOT EXISTS auth (id int, user varchar(32), ip varchar(15), data int, PRIMARY KEY (id))';
if(!$create = $db->prepare($query)){
        print_r($db->errorInfo()); die();
}
$query = 'DELETE FROM auth WHERE data < "'.(time()-60*60*5).'"';
if(!$delete = $db->prepare($query)){
        print_r($db->errorInfo()); die();
}
$query = 'SELECT COUNT(*) FROM auth WHERE user = "'.$_SERVER['REMOTE_USER'].'" AND ip = "'.$_SERVER['REMOTE_ADDR'].'"';
if(!$count = $db->query($query)){
        print_r($db->errorInfo()); die();
}
if($count->fetchColumn() < 1){
        if(!$insert = $db->query('INSERT INTO auth (user, ip, data) values ("'.$_SERVER['REMOTE_USER'].'", "'.$_SERVER['REMOTE_ADDR'].'", "'.time().'")')){
                print_r($db->errorInfo()); die();
        }
}else{
        if(!$update = $db->query('UPDATE auth SET data = "'.time().'" WHERE user = "'.$_SERVER['REMOTE_USER'].'" AND ip = "'.$_SERVER['REMOTE_ADDR'].'"')){
                print_r($db->errorInfo()); die();
        }
}

header("Location: .");

Now you have a database and can auto limit so only a specified ip can access those files without a password for a specified time :)

This .htaccess will redirect all requests for those .ex1, .ex2 and .ex3 extensions that also come with a specified browser to play.php which will check the sqlite db and passthrough the requested file .. also, we will be replying a 403 for any dir index from those browsers...

Options +Indexes
SetEnvIf Request_URI "\.ex1$" DEXISFILE=yes
SetEnvIf Request_URI "\.ex2$" DEXISFILE=yes
SetEnvIf Request_URI "\.ex3$" DEXISFILE=yes
SetEnvIf User-Agent "^some" DEXISPLAYER=yes
SetEnvIf User-Agent "^browser" DEXISPLAYER=yes
SetEnvIf User-Agent "^thing" DEXISPLAYER=yes
RewriteEngine On
RewriteBase /path/to/play/
RewriteCond %{ENV:DEXISPLAYER} ^yes$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [F,L]
RewriteCond %{ENV:DEXISFILE} ^yes$
RewriteCond %{ENV:DEXISPLAYER} ^yes$
RewriteRule ^ play.php?file=%{REQUEST_FILENAME} [L]
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /path/to/.passwords
AuthGroupFile /path/to/.groups
<RequireAny>
        Require group somegroup anothergroup
        <RequireAll>
                Require env DEXISFILE
                Require env DEXISPLAYER
        </RequireAll>
</RequireAny>

Here's the play.php file

<?php
function ftype($file){
        $fi = new finfo(FILEINFO_MIME);
        $mime_type = $fi->file($file);
        return $mime_type;
}
if(!isset($_SERVER['REMOTE_ADDR'])){
        $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
}
if(!isset($_SERVER['REMOTE_USER'])){
        $_SERVER['REMOTE_USER'] = 'cli';
}
$db = new PDO('sqlite:/tmp/sqlite.db');
$query = 'CREATE TABLE IF NOT EXISTS auth (id int, user varchar(32), ip varchar(15), data int, PRIMARY KEY (id))';
if(!$create = $db->prepare($query)){
        print_r($db->errorInfo()); die();
}
$query = 'SELECT COUNT(*) FROM auth WHERE ip = "'.$_SERVER['REMOTE_ADDR'].'" AND data > '.(time()-5*60*60);
if(!$count = $db->query($query)){
        print_r($db->errorInfo()); die();
}
if($count->fetchColumn() > 0){
        $file = $_GET['file'];
        $fh = fopen($file, 'rb');
        header("Content-Type: ".ftype($file));
        header("Content-Length: " . filesize($file));
        fpassthru($fh);
}else{
        header('HTTP/1.0 403 Forbidden');
}