Notice in the linked article, the technique relies on system()
which should be disabled on public-facing PHP processors. Disabling that, and other crazy funcs, should stop a large percentage (ie. shell_exec
, passthru
, exec
, popen
, proc_open
, ... see https://globedrill.com/disable-dangerous-php-functions-php-hardening-cpanel/) - this control applies to the PHP configuration php.ini
option disable_functions
. Another relevant option is open_basedir
, which is used to restrict file inclusion or operations to directories under this value.
In the context of what reaches the web server, WAFs can be configured to 400
any attempts to inject code into the log via a HTTP request, by blocking the request at the gate.
With respect to what is logged, the web server can ensure user-controlled contents in the log are rendered inert by encoding any data before writing, eg urlencode
. This is a sensible thing to establish, at the service layer, as well as the application layer.
At another level, more control can be applied to the directories where log files are placed, and the access that applications have to these dirs. This can be handled by chmod
et al. to limit the access, preventing PHP running under the context of the web server to access the log file. Depending on how the server is configured, this probably wouldn't be possible for the web server's logs (at least without some hoop-jumping), but for application logs etc.
Also worth mentioning, .htaccess
or equiv can be used to reject any requests for known log files, eg. PHP's error_log
.
Finally, within the PHP itself, where the file is brought in with include
, require
et.al, some filtering could be applied to ensure that the value prepared from user-input is within an acceptable range, possibly by using a regex, eg:
<?php
echo preg_match( '/file1\.php|file2\.php|file3\.php/', $lang_consts_file );