(Backstory: My PHP script is executing another PHP script through the command line (PHP's "exec()" command) so that the cURL session the target script creates doesn't cause the original PHP script to hang. I'm doing this so that I can send transactional email without slow page loads for my user if the email provider's servers are laggy.)
I'm calling a PHP script like this:
exec("[php] [target script] [querystring]"), where [querystring] is a typical HTTP GET querystring (variable=value&variable2=value2). The reason I'm passing the email data to the target script via a querystring is that my PHP host has a flag disabled in the PHP.ini that disallows PHP scripts from detecting the $argv's they're called with via the command line. (For whatever reason, appending a querytring works though.)
So, the question is: What would be the character limit on this querystring? Would there even be one? There is no HTTP or web browser in the mix -- would this mean Apache's and browsers' GET character limits wouldn't be a constraint? Would there naturally be a command line constraint, though?
I don't think there is any character limit, if it is, it's probably determined by the operating system that you use or the language which in this case would translate to your memory.
I hope that answers your question.
Please note that PHP setups with the suhosin patch installed will have a default limit of
512 characters for get parameters. Although bad practice, most browsers (including IE)
supports URLs up to around 2000 characters, while Apache has a default of 8000. To add
support for long parameters with suhosin, add suhosin.get.max_value_length = in php.ini
Related
I have the following setup:
Some files are dynamically generated dependent on some (only a few) session parameters. Since they have not a great diversity, i allow caching in proxys/browsers. The files get an etag on their way, and the reaction of the whole web application at first glance seems correct: Files served in correct dependence from session situations, traffic saved.
And then this erroneous behavior:
But at closer inspection, i found that in his answer in case of a 304 for those dynamically generated files, apache wrongly sends a "Connection: close" Header instead of the normally sent "Connection: KeepAlive". What he should do is: Simply do not manipulate anything concerning "connection".
I cannot find any point where to pinpoint the cause of this behavior: Nowhere in the apache config files is anything written except one single line in one single file where it is instructed to send a keepalive - which it does - as long as it does not send a 304 response for a dynamically generated file. Nowhere in PHP do i instruct that guy to send anything other than keepalives (and the latter only to try to counter the connection:close).
The apache does not do this when it serves "normal" (non-dynamic) files (with 304 answers). So in some way i assume that maybe the PHP kernel is the one who interferes here without permission or being asked. But then, an added "Header set Connection 'Keep-Alive'" in the apache config, which i too added to counter the closing of the connection, does not work, too. Normally, when you put such a header set rule (not of "early" type) in the apache config, this rules takes action AFTER finalization of any subordered work on the requested document (thus AFTER finalization of the PHP output). But in my case, nothing happens - well: in case of a 304 response. In all other cases, everything works normal and correct.
Since there do some other files go over the line at a page request, i would appreciate to get the apache rid of those connection-closures.
Is there anybody who has an idea what to do with this behavior?
P.S.: One day (and a good sleep) later, things are clearing:
The culprit in this case was a shortsightedly (on my behalf) copied example snippet, which had "HTTP/1.>>>0<<< 304" (the Null!) in it.
This protocol version number gets (correctly) post-processed by apache (after everything otherwise - including any apache modules work - got finalized), in that it decides not to send a "Connection: Keep-Alive" over the wire, since that feature didn't exist in version HTTP/1.0.
The problem in this case was to get the focus on the fact that everything inside php and apache modules worked correctly and something in the outer environment of them must have been wrong, and thereafter to shift the view to anything in the code that could possibly influence that outer environment (e.g. the protocol version).
I have to distribute a huge file to some people (pictures of a prom) via my Apache2/PHP server which is giving me some headaches: Chrome and Firefox both show a filesize of 2GB but the file is actually >4GB, so I started to track things down.
I am doing the following thing in my php script:
header("Content-Length: ".filesize_large($fn));
header("Actual-File-Size: ".filesize_large($fn)); //Debug
readfile($fn);
filesize_large() is returning the correct filesize for >4gb files as a string (yes, even on 32-bit PHP).
Now the interesting part; the actual HTTP header:
Content-Length: 2147483647
Actual-File-Size: 4236525700
So the filesize_large() method is working totally fine, but PHP or Apache somehow limit the value of Content-Length?! Why that?
Apache/2.2.22 x86, PHP 5.3.10 x86, I am using SSL over https
Just so you guys believe me when I say filesize_large() is correct:
function filesize_large($filename)
{
return trim(shell_exec('stat -c %s '.escapeshellarg($filename)));
}
Edit:
Seems like PHP casts the content length to an integer when communicating with apache2 over the sapi interface on 32-bit systems. No workaround sadly except not including the Content-Size in case of files >2GB
Workaround (and actually a far better solution in the first place): Use mod_xsendfile
You have to use 64-bit operation system in order to support long integers for Content-length header.
I would recommend to use Vagrant for development.
Header based on strings, but content length based on int. If take a look here https://books.google.com/books?id=HTo_AmTpQPMC&pg=PA130&lpg=PA130&dq=ap_set_content_length%28r,+r-%3Efinfo.size%29;&source=bl&ots=uNqmcTbKYy&sig=-Wth33sukeEiSnUUwVJPtyHSpXU&hl=en&sa=X&ei=GP0SVdSlFM_jsATWvoGwBQ&ved=0CDEQ6AEwAw#v=onepage&q=ap_set_content_length%28r%2C%20r-%3Efinfo.size%29%3B&f=false
you will see example of ap_set_content_length(); function which was used to serve content-length response. It accepts file length from system function. Try to call php filesize() and you'll probably see the same result.
If you take a look into ap_set_content_length declaration http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#ga7ab393c56cf073ce7aadc3b7ca3db7b2
you will see that length declared as apr_off_t.
And here http://svn.haxx.se/dev/archive-2004-01/0871.shtml you can read, that this type depends from compiler options which is 32bit in your case.
I would recommend you to read source code of Apache and PHP projects.
I've just received the following error from a few sites I run:
Error Caught in Application_Error event
Error in:
https:///phppath/php?-d+allow_url_include=on+-d+safe_mode=off+-d+suhosin.simulation=on+-d+disable_functions=""+-d+open_basedir=none+-d+auto_prepend_file=php://input+-n
Error Message:A potentially dangerous Request.Form value was detected
from the client (="Stack Trace: at
System.Web.HttpRequest.ValidateString(String value, String
collectionKey, RequestValidationSource requestCollection)
Obviously, the ASP.NET has just rejected this - a good thing.
But what I do not understand, not being a PHP type chap, is what it is trying to do?
The attacker has sent PHP code in the HTTP request body, and he is trying to have that code executed by your web server.
The php://input references the request body (ie POST data). The auto_prepend_file directive allows the script to include PHP code in the same way that include() and require() work. If successful, the uploaded code would be prepended and executed.
The payload most likely contains a backdoor script and some code to call home to let the developer know that a hack was successful.
This is most likely a bot that has randomly selected your server, as opposed to a human manually attempting it.
The bug that the attacker is trying to exploit is CVE-2012-1823:
sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not properly handle query strings that lack an = (equals sign) character, which allows remote attackers to execute arbitrary code by placing command-line options in the query string, related to lack of skipping a certain php_getopt for the 'd' case.
http://www.cvedetails.com/cve/CVE-2012-1823
$output = file_get_contents("http://www.canadapost.ca/cpc2/addrm/hh/current/indexa/caONu-e.asp");
var_dump($output);
HTTP 505 Status means the webserver does not support the HTTP version used by the client (in this case, your PHP program).
What version of PHP are you running, and what HTTP/Web package(s) are you using in your PHP program?
[edit...]
Some servers deliberately block some browsers -- your code may "look like" a browser that the server is configured to ignore. I would particularly check the user agent string that your code is passing along to the server.
Check in your PHP installation (php.ini file) if the allow_url_fopen is enabled.
If not, any calls to file_get_contents will fail.
It works fine for me.
That site could be blocking the server that you're using to access it.
When you run the URL from your browser, your own ISP is used to get the information and display in your browser. But when you run from PHP, the ISP of your web host is used to get the information, then it passes it back to you.
Maybe you can do this to check and see what kind of headers its returning for you?
$headers=get_headers("http://www.canadapost.ca/cpc2/addrm/hh/current/indexa/caONu-e.asp");
print_r($headers);
I have a form which sends data with the POST method, about 3000 array keys to be inserted in MySQL like this:
client_add[]=1
client_add[]=3
client_add[]=47
...
The problem is on my localhost on the development server works just fine. On production I only get about 1000 rows, on the localhot it seems to get lost, we confronted the php.ini files and the development server has everything set to more memory than my localhost.
I've run out of ideas.
The size of the post body will be somewhere around 50kb, which is ok as long as the server and/or PHP doesn't enforce a limit. It seems like your production environment enforces such a limit. You should check the entire webserver configuration, and if that is identical as well, compare compile-time defaults. Maybe the phpinfo() call shows more on the actual limits.
PHP has an ini setting which dictates the size of your POST request, you can probably find it in your ini under the name of post_max_size.
Also, if you've got the Suhosin patch installed it will enforce a limit on the number of POST variables you can submit on each request. I think this is around 2000 by default.