Organizational Research By

Surprising Reserch Topic

Experts Most Trusted Topic


break http file uploading from server side by php or apache


break http file uploading from server side by php or apache  using -'php,node.js,http,mod-rewrite,file-upload'

When uploading big file (>100M) to server, PHP always accept entire data POST from browser first. We cannot inject into the process of uploading.

For example, check the value of "token"  before entire data send to server is IMPOSSIBLE in my PHP code:

<form enctype="multipart/form-data" action="upload.php?token=XXXXXX" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="3000000" />
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>


So I've try to use mod_rewrite like this:

RewriteEngine On
RewriteMap mymap prg:/tmp/map.php
RewriteCond %{QUERY_STRING} ^token=(.*)$ [NC]
RewriteRule ^/upload/fake.php$ ${mymap:%1} [L]


map.php

#!/usr/bin/php
<?php
define("REAL_TARGET", "/upload/real.php\n");
define("FORBIDDEN", "/upload/forbidden.html\n");

$handle = fopen ("php://stdin","r");
while($token = trim(fgets($handle))) {
file_put_contents("/tmp/map.log", $token."\n", FILE_APPEND);
    if (check_token($token)) {
        echo REAL_TARGET;
    } else {
        echo FORBIDDEN;
    }
}

function check_token ($token) {//do your own security check
    return substr($token,0,4) === 'alix';
}


But ... It fails again. mod_rewrite looks working too late in this situation. Data still transfer entirely.

Then I tried Node.js, like this (code snip):

var stream = new multipart.Stream(req);
stream.addListener('part', function(part) {
    sys.print(req.uri.params.token+"\n");
    if (req.uri.params.token != "xxxx") {//check token
      res.sendHeader(200, {'Content-Type': 'text/plain'});
      res.sendBody('Incorrect token!');
      res.finish();
      sys.puts("\n=> Block");
      return false;
    }


Result is ... fail again.

So please help me to find the correct path to resolve this issue or tell me there is no way.

Related questions:

Can PHP (with Apache or Nginx) check HTTP header before POST request finished?

Can some tell me how to make this script check for the password before it starts the upload process instead of after the file is uploaded?
    

asked Sep 29, 2015 by ajit.chavhan
0 votes
2 views



Related Hot Questions



Government Jobs Opening

Send this file:
answered Sep 29, 2015 by deepak gupta
0 votes

I suggest you to use some client side plugins to upload files. You could use

http://www.plupload.com/

or

https://github.com/blueimp/jQuery-File-Upload/

Both plugins have provision to check file size before uploading.

If you want to use your own scripts, check this. This may help you

        function readfile()
        {
            var files = document.getElementById("fileForUpload").files;
            var output = [];
            for (var i = 0, f; f = files[i]; i++) 
            {
                    if(f.size < 100000) // Check file size of file
                    {
                        // Your code for upload
                    }
                    else
                    {
                        alert('File size exceeds upload size limit');
                    }

            }
        }
answered Sep 29, 2015 by vimaldas2005
0 votes

Previous version was somewhat vague. So I've rewritten the code to show the difference between route handling and middleware. Middlewares are executed for every request. They are executed in the order they are given. express.bodyParser() is the middleware which handles file upload, which you should skip, for incorrect tokens. mymiddleware simply checks for tokens and terminates invalid requests. This must be done before express.bodyParser() is executed.

var express = require('express'),
app = express();

app.use(express.logger('dev'));
app.use(mymiddleware);                                 //This will work for you.
app.use(express.bodyParser());                         //You want to avoid this
app.use(express.methodOverride());
app.use(app.router);

app.use(express.static(__dirname+'/public'));
app.listen(8080, "127.0.0.1");

app.post('/upload',uploadhandler);                     //Too late. File already uploaded

function mymiddleware(req,res,next){                   //Middleware
    //console.log(req.method);
    //console.log(req.query.token);
    if (req.method === 'GET')
        next();
    else if (req.method === 'POST' && req.query.token === 'XXXXXX')
        next();
    else
        req.destroy();
}

function uploadhandler(req,res){                       //Route handler
    if (req.query.token === 'XXXXXX')
        res.end('Done');
    else
        req.destroy();
}

uploadhandler on the other hand cannot interrupt the upload as it has been processed by express.bodyParser() already. It just processes the POST request. Hope this helps.

answered Sep 29, 2015 by shikhar jain
0 votes

One way to bypass PHP's post handling is to route the request through PHP-CLI. Create the following CGI script and try uploading a large file to it. The web server should respond by killing the connection. If it does, then it's just a matter of opening an internal socket connection and sending the data to the actual location--provided that conditions are met, of course.

#!/usr/bin/php

answered Sep 29, 2015 by sachin wagh
0 votes

Why dont you just use the APC file upload progress and set the progress key as the key for the APC file upload so in that case the form is submitted and the upload progress will start initially but then at the first progress check you will verify the key and if its not correct you will interrupt everything:

http://www.johnboy.com/blog/a-useful-php-file-upload-progress-meter http://www.ultramegatech.com/2008/12/creating-upload-progress-bar-php/

This is a more native approach of doing it. Roughly the same, just change the key of the hidden input to your token and validate that and interrupt the connection in case of an error. Maybe thats even better. http://php.net/manual/en/session.upload-progress.php

answered Sep 29, 2015 by yogeshplv

...