Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access logging in PHP

I want to log access to any files in the /files folder, so I can process it with PHP to generate some statistics.

I don't want to write a custom PHP handler called via RewriteRule because I don't want to have to deal with status codes, MIME-types and caching headers, and file locking issues.

I don't have access to the server configuration, so I can't use CustomLog (I do have access to .htacess).

I can't use X-Sendfile because it's not enabled.

I don't have access to the access.log.


Looking for an authorative answer.

like image 887
Halcyon Avatar asked Jan 31 '12 16:01

Halcyon


People also ask

How do I access PHP logs?

Look for the entry Configuration File (php. Find the Error handling and logging section of the php. ini file. Make sure that both display_errors = On, display_startup_errors = On and log_errors = On are present and uncommented. Check the value of error_log - this tells you the location of the file errors are logged to.

How do I enable PHP logging?

Enable Error Logging in php. If you want to enable PHP error logging in individual files, add this code at the top of the PHP file. ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); Now, you must enable only one statement to parse the log errors in the php.

What is PHP system logger?

Logs provide exhaustive, robust information that is useful for tracking all the changes made to an application's code. PHP logs help you track the performance of the method calls within your application, the occurrence of a particular event, and the errors in your application.


4 Answers

That's quite a few restrictions you've placed there.

You can do this with a custom handler installed via a PHP include at the top of each applicable (or, with __FILE__ parsing, not applicable) script. You must have a script which runs when each file is hit, and you've excluded alterations to the server config (including, I believe, .htaccess when you said RewriteRule wasn't good enough), so that means that you will be doing this through a script-based gatekeeper. You cannot have a solution which meets your constraints and has users go to files without hitting PHP (or another server-side dynamic language) first. Caching can be preserved by redirecting the user to the actual files instead of running static content through PHP.

You can store the log information in a database, or a file in a location writable by the server (watch out for contention if you use files - append mode is tricky).

EDIT: quickshiftin points out two ways you can get PHP invoked without having to add include calls by hand.

like image 88
Borealid Avatar answered Oct 19 '22 12:10

Borealid


Create an auto_prepend_file and define a function to log w/e you want. You'll need access to .htaccess in order to set these (and the webhost will need something like AllowOverride all in the vhost) or with PHP 5.3 you can use the per-directory INI feature.

.htaccess

php_value auto_prepend_file /path/to/file.php

per-directory php.ini (PHP 5.3 CGI/Fast CGI SAPI)

user_ini.auto_prepend_file = /path/to/file.php

Then for your file /path/to/file.php (something more elegant I'm sure ;))

file_put_contents(
    LOG_FILE,
    implode(PHP_EOL . PHP_EOL, array(
                'SERVER: ' . PHP_EOL . print_r($_SERVER, true),
                'REQUEST: ' . PHP_EOL . print_r($_REQUEST, true)
            )),
    FILE_APPEND
);

The beauty of this approach is you'll likely be able to get away with it and you'll only need to define / include the logging code in one place.

EDIT:

Upon retrospection I see you want this to work for arbitrary types of files... Yes that would be rather rough. Best bet I can think of is labeling these files as .php or defining custom mime types in .htaccess. The idea would be to run the files through the PHP interpreter, thereby executing the auto_prepend_file and since there are no PHP tags in the file the content is sent directly to the client. Maybe even a tiny bit of PHP atop each file of content setting the ContentType header. I'm not even sure that would work but it might.

like image 21
quickshiftin Avatar answered Oct 19 '22 12:10

quickshiftin


That's pretty simple to do considering you don't need to restrict access.

build a page logger.php that takes in input the file requested like:

logger.php?file=abc.exe

In the logger.php you just have to log this access then rediret to the file:

file_put_contents('log', $_GET['file'] . ' requested',FILE_APPEND);
header('Location: files/'.$_GET['file']);

Just check the $_GET['file'] for malicious files

Of course you have to replace links in your site, from:

<a href="files/abc.exe">

to

<a href="logger.php?file=abc.exe">
like image 3
dynamic Avatar answered Oct 19 '22 12:10

dynamic


It seems like the intention here is to circumvent all the systems that are inherently in place in Apache and PHP. If these restrictions are actually in place on your server instance you are far much better off asking for a change to your privileges than devising a workaround that your system admin may or may not be happy with you implementing.

like image 3
PFY Avatar answered Oct 19 '22 13:10

PFY