This may seem like a funny question but in fact it's not, I would like to disable echo, print and other functions that may output to the buffer such as readfile.
The reason why I would like to do this is to prevent the client from using echo or print outside the rules of my application, forcing them to compile their contents and send it to the output class, so that the whole buffer is managed.
Now I know I can set up an output buffer at the start of my script and throw away any content, but this will not include things such as header and set_cookie, so my question may be interpreted as How can I control the buffer for the head of the response
Is there any possible way to manage all aspects of PHP's outputting, such as assign a callback to the main buffer rather then just the body of response?
At the end there is no effective way to achieve this, because at least echo is not a function, but a language construct, that cannot get disabled. You may play around with output buffering (ob_start() and such), but that will not prevent other code to disable the output buffering again.
In my eyes there is no way around but to make sure, there is only "good code". I don't know, what you mean by "prevent the client", but I would not execute arbitrary code anyway. And if its written by disciplined developers and its tested, there should be no problem then.
Other than editing and recompiling, I don't believe you can disable functions that output. For functions that bypass output buffering, your SOL.
You can, however, use inline output buffering to control non-header output. The best part is it's nesting capability:
ob_start();
echo 'The first output!',"\n";
ob_start();
echo 'The second output.';
$output2 = ob_get_clean();
ob_flush();
echo $output2;
will output:
The first output!
The second output.
What you want to do - prevent outputting at runtime - isn't possible. It just isn't going to happen. You can get very close if you do these two things though: audit the code for keywords that can produce output, and buffer output while preventing access to the output buffer control functions.
Audit the code programmatically to make sure certain untrappable situations don't exist (it's up to you to cache the result of that audit efficiently, or just eat the cost of auditing on every page view - not recommended).
You can use token_get_all() to audit for output keywords such as T_ECHO and T_PRINT (here is a list of all possible tokens). Don't try to disable access to anything but keywords here, there's too many ways to trick that (eval(), variable variables, data:// streams, etc.) You're only blocking certain keywords here.
Don't forget T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, and T_REQUIRE_ONCE. Not only could these be used to include unaudited code (such as PHP code written to a temp file then included), but using some of the more advanced file wrappers, these themselves can be used to produce output.
Use the PHP ADB extension to disable access to certain methods by renaming them. Don't try to disable output functions, it's just not going to work, there's too many ways to generate output. Pick out the special ones like set_cookie() and header(), but for actual output, there's innumerable ways to produce output. The only surefire way to block this is to use output buffering, but disable access to the output buffer control methods so they have no way to bypass buffering.
class YourApplicationControllingClass {
final protected function callUserCode($pathToUserCodeFile) {
// We want this to be a local variable so there's no way to get to it
// with PHP Reflection
$suspender = new SuspendFunctions();
ob_start();
// You may need to add more here, this is just my superficial pass
$suspender->suspend("ob_clean", "ob_end_clean", "ob_end_flush", "ob_flush",
"ob_get_clean", "ob_get_contents", "ob_get_flush", "ob_get_length",
"ob_get_level", "ob_get_status", "ob_implicit_flush", "ob_list_handlers",
"ob_start", "output_add_rewrite_var", "output_reset_rewrite_vars",
"set_cookie", "set_raw_cookie", "header_register_callback", "header",
"header_remove", "http_response_code", "register_shutdown_function",
"register_tick_function", "unregister_tick_function", "set_error_handler",
"restore_error_handler", "set_exception_handler", "restore_exception_handler"
);
$this->callUserCodeSandbox($pathToUserCodeFile);
// Restore our original execution environment
$suspender->resume();
$content = ob_get_clean();
// If you want to be aggressive, check to see if they produced any output
// and blacklist them if they even try.
if ($content !== '') $this->blacklistUserCode($pathToUserCodeFile);
}
private function callUserCodeSandbox($pathToUserCodeFile) {
require($pathToUserCodeFile);
}
}
final class SuspendFunctions {
private $suspendedFunctions = array();
/**
* Suspends certain functions from being executable.
* #param string $function,... Names of functions to suspend, you may pass multiple
* #return void
*/
function suspend($function) {
$functions = func_get_args();
foreach($functions as $function) {
// Make sure we don't double-suspend a function
if (isset($this->suspendedFunctions[$function])) continue;
// Make new names unguessable, and make it very unlikely that we end up with a collision.
$newName = '_'.md5($function.microtime(true).mt_random());
// Rename to the unguessable name
rename_function($function, $newName);
// Keep a record for ourselves what this new name is so we can resume later
$this->suspendedFunctions[$function] = $newName;
}
}
/**
* Resumes functions for calling
*/
function resume() {
foreach($this->suspendedFunctions as $function=>$newName) {
rename($newName, $function);
unset($this->suspendedFunctions[$function]);
}
}
}
Just be aware, no matter how good you are at this, there's almost certainly going to be a way to bypass (for example, maybe their code patches the content of one of your application's files to permit output again). PHP is too flexible to lock this down solidly. PHP had a similar project called Safe Mode, which they eventually abandoned because it was impossible to totally securely lock everything down. As long as the user has a full execution environment, anything you can do to block them, they can undo. Very unwise in general to execute user contributed code without hand-auditing each and every line (and even dangerous then).
do it this way :
function trace($message) {
$echo = true;
if ($echo)
echo $message . "<br>";
}
then just call trace("your message"); anytime you need it, and switch $echo to false to disable it globally
Related
When single-stepping through PHP code during debugging (e.g. in Netbeans) I want to see PHP output in my browser immediately. This can be achieved (at least when using PHP7.2 and Firefox) by including the following at the start of the PHP code:
ob_implicit_flush ();
while (#ob_end_flush());
This ensures that things like
echo "foo\n";
immediately result in 'foo' being displayed in the web browser rather than when the output buffer is due for a flush or the PHP code exits upon completion or error.
But is there a way to achieve this by editing php.ini so I don't have to include it in every bit of PHP code to be debugged? (I understand this will result in a performance penalty, but this is for development and debugging purposes only.)
Flushing the output buffer is an implicit action that the developer must make, so isn't something that can be toggled on or off in the php.ini.
However, PHP does have a feature called ticks, which allows the developer to register a callback function to be called every X lines of code that are executed.
See register_tick_function, where you can define your own callback function to perform the flush, and have it run in between every statement in your program. This will obviously kill performance, and there is probably a better way of achieving what you're trying to do.
Example:
declare(ticks=1);
function autoFlushBuffer() {
ob_implicit_flush ();
while (#ob_end_flush());
}
register_tick_function("autoFlushBuffer", true);
// The following lines will appear in your web browser one by one:
echo "one";
sleep(1);
echo "two";
sleep(1);
echo "three";
sleep(1);
Good day!
I am having some issues with getting the echo statement to output before the execution of the exec()
<?
if (isset($_POST['ipaddress'])) {
$escaped_command = escapeshellcmd($_POST['ipaddress']);
if(filter_var($escaped_command, FILTER_VALIDATE_IP)) {
echo "Gleaning ARP information, please wait..";
$command = exec('sudo /sbin/getarp.exp');
The echo statement is being outputted after the execution of the $command. The execution time can be anywhere from 15-30 seconds depending on how large the ARP table on the remote router is. Is there an order of operations that I am not aware of? It appears that all the statements within the if statement are executed in parallel and not by line by line as I had assumed.
I would rather not a solution be provided, but some documentational links that would lead me to finding a solution. I have searched what I could, but was not able to find a viable solution.
Any help would be appreciated.
Thanks.
This is happening because the script will run in its entirety before any result/output is sent to the browser.
In PHP there is a concept of "output buffering".
Whenever you output something (e.g. using echo, print, etc.) the text is thrown into a buffer. This buffer is only sent at certain times (at the end of the request, for instance, or when the buffer is full).
In order to empty the buffer (to "flush" it) you need to do it manually. The flush() function will do this. Sometimes you also need to call ob_flush() (this is if you have opened custom output buffers yourself). It is generally a good idea to just call both functions and be done with it:
echo 'Wait a few seconds...';
flush(); ob_flush();
sleep(3);
echo ' aaand we are done!';
See Output Buffering Control for more information on output buffering in PHP.
This is probably an issue with the output buffer. PHP buffers output and writes it to the browser in chunks. Try adding a call to ob_flush() between the echo and the exec(); this will force PHP to write the current contents of the buffer to the browser.
By default, php does not send any of the output until the php script is done running completely. There is a solution. However, I hear it is a little browser dependent. I would test it on different systems and browsers to see if it is working:
ob_implicit_flush (true)
Put that before any of your echo/print commands and that should allow anything printed to show right up on the browser.
A more universal approach would be to integrate your page with asynchronous javascript. A process commonly referred to as "AJAX". It is a little more difficult because it requires the use of many interacting scripts, some client-side and some server-side. However, AJAX is the defacto way to do thing like this on the web.
Hopefully someone here can help me out - basically I have a logging class that I'm updating (Made it ages ago), and I want to make sure it logs messages under 98-99% of circumstances. However right now it doesn't handle exit()s, it basically just writes to a file (Opening, writing, and closing) every time a message/error is sent to the logger.
What would be the best way to handle exit()s, and be efficient in terms of disk writes? Right now I'm looking at __destruct in the logger class (With fopen, fwrite, and fclose being called in it), however I'm not quite sure if this is safe, or efficient.
Edit: What about set_error_handler()? I remember reading years ago that this was very slow and not very good for custom errors/messages (Like SQL issues)
If you wish to log something when your script ends, you should take a look at PHP's register_shutdown_function():
function shutdown()
{
// .. log code here.
}
register_shutdown_function('shutdown');
You should avoid using the __destruct() method as there is no guarantee that it will be called when you expect it to be called.
You could also take a look at PHP's built in error_log() method to write the contents to the actual PHP error log file (this is possibly more reliable than writing your own logger).
References:
http://php.net/manual/en/function.register-shutdown-function.php
http://php.net/manual/en/function.error-log.php
I always use some global function, e.g.
function BeforeExit () {
//do stuff like logging
exit;
}
What I want to do is when an if condition doesn't go as it should, instead of echo'ing the my custom error message in else { }, storing the error message somewhere else and retrieving it from another page.
For example, this is my page with the if condition:
if ($something < 4){
echo 'yes it is less than four';
else { echo 'no it isn\'t less than four';}
I want to for example store these error messages in strings and give them numbers:
if ($something < 4){
$debug11 = 'yes it is less than four';
echo '11';
else { $debug10 = 'no it isn\'t less than four'; echo '10'; }
then let's assume there's a debug.php file with php class that can echo these messages but in order to do so it needs to know what $debug11 is, can it do that without including that php page? is that what public strings are for? or should I just define all of them in debug.php
the point of all this is that jquery will call this file.php and get a message like 11 or 10 which in this case is success or failure then I will be able to know why it failed with debug.php. numbers are easier since I may play with text messages a lot and easier to confirm with numbers than text in if conditions.
You want to store error-messages and read this messages by another script.
It means you need a storage.
As a storage, you can use files, or memcache, or APC, or queues.
Create logger, which will write messages to the storage, and then in debug.php you will read list of messages from the storage.
I recommend to use Memcache, set_error_handler and trigger_error.
I'm not sure what you mean by 'public strings', but if you are looking at accessing a variable between 2 pages, you would need to persist them into a session variable at least.
Also you might be better off using PHP assertions to check for error conditions within your code (I think that's what your trying to achieve here):
Assertions should be used as a debugging feature only. You may use them for sanity-checks that test for conditions that should always be TRUE and that indicate some programming errors if not or to check for the presence of certain features like extension functions or certain system limits and features.
Try logging to file: http://nl3.php.net/manual/en/errorfunc.configuration.php#ini.error-log. You can supply a custom log file in which you can find all your errors.
If you put in a error handler you should be able to create debug messages and store them in another file.
Write own logging mechanism and put log messages in a file.
As above I am not 100% sure what you are trying to do, however instead of using variables for your custom error messages it may be better to use Constants. The benefits of them are that the values can't be rewritten unlike your variable where you can change the value within your script.
Your code would look something like this:
define("ERROR1", "It wont Work!");
define("ERROR2", "It still wont Work!");
define("ERROR3", "It must be broken!");
if ($something < 4){
echo '11';
} else {
echo ERROR1; // Prints "It wont Work!"
}
You can store these Constants in your debug.php file and use them on any page you include the file on.
Hope this helps.
I'm using Zend_Reflection to generate an extended format set of ctags for use with my text editor. The problem is that you have to include any files that you wish to process.
The constructor for Zend_Reflection_File checks to see if the file you wish to reflect has been included, and if not it throws an exception:
// From Zend/Refection/File.php (94-97)
if (!$fileRealpath || !in_array($fileRealpath, get_included_files())) {
require_once 'Zend/Reflection/Exception.php';
throw new Zend_Reflection_Exception(
'File ' . $file . ' must be required before it can be reflected');
}
I only use this technique on code that I trust but I'd like to wrap it all up in a script for others to use. My concern is that any included files may introduce unsafe code into the current scope. For example, I wouldn't want to include the following:
<?php
// evil.php
shell_exec('rm -rf /');
My first thought was to use safe_mode but this is depreciated (and not as safe as the name would suggest it seems).
The next idea would be to use a custom php.ini file and the disable_functions directive but (beyond the candidates listed in the safe_mode documentation) I couldn't be sure that I'd caught all the necessary functions.
Finally I'm wondering if there's any way of making PHP run in a sandbox (of sorts) -- I'd like to capture the Reflection information without any global code that was included being executed at all.
Any and all thoughts appreciated.
TIA.
You shouldn't be including, or eval-ing, user supplied code.
Edit:
Trying to filter out "safe" code is beyond the scope of Zend_Reflection. That is not the intended usage, and is not supported by the framework. If you wish to do some voodoo token parsing on your input, feel free, but that isn't Zend_Reflection.
Edit 2:
If you really want to do this, please look at token_get_all, token_get_name, and the list of parser tokens.
If you look at the Zend_Reflection_File::_reflect method, you can get an idea of what you could do:
<?php
$tokens = token_get_all(file_get_contents('file.php'));
foreach ($tokens as $token) {
if (is_array($token)) {
$type = $token[0];
$value = $token[1];
$line = $token[2];
}
switch ($type) {
case T_FUNCTION:
if ($value == 'shell_exec') {
throw Exception("WTF");
}
// etc.
}
}