grigoryvp
grigoryvp

Reputation: 42593

How to figure out what code include'd specified .php file?

I have a third-party web server with Ubuntu 14.04 and PHP 5.5.3 running some wordpress stuff. Using logs I figured out what some .php file seems to be a part of a backdoor/spambot and sending a spam. But according to website architecture this file must not be included at all. I can add code to that file and require a stacktrace:

$e = new Exception;
file_put_contents('/tmp/debug.log', $e->getTraceAsString());

But stacktrace contains only:

#0 {main}

It seems that file is included or required from a top-level scope. Is it any way for me to figure out where a file is required from? Like name of .php file and a line where require or include is called?

Update

Since I have two answers suggesting debug_backtrace I must clarify that it's same as getTraceAsString and evaluates to an empty array (I tested it manually).

Upvotes: 1

Views: 169

Answers (5)

Eugen Mihailescu
Eugen Mihailescu

Reputation: 3721

I solved a similar problem and hopefully my solution will help you too. Given that I have a project of 300+ .php source files I wanted to know what is the set S of .php files that my file F depends on.

All you need to do is to

  1. scan the project directory and for each .php file you need to parse the file's content for those includes|requires statements then extract those filenames and
  2. create a graph with all this information.

By using Dijkstra's shortest path algorithm determine what's the shortest path between one chosen file any other file of the project. So basically you'll get a dependency tree that will tell you more than you need.

@Edit: if interested then read more about this.

Upvotes: 1

DanielM
DanielM

Reputation: 6676

If you just want a list of php files that have been included/required then there's a function for that.

I've never used it before, but from that page:

<?php
// This file is abc.php

include 'test1.php';
include_once 'test2.php';
require 'test3.php';
require_once 'test4.php';

$included_files = get_included_files();

foreach ($included_files as $filename) {
    echo "$filename\n";
}

The above example will output:

abc.php
test1.php
test2.php
test3.php
test4.php

It's worth noting though, that unless you know otherwise, the spam bot thing is unlikely to be in a separate PHP file, it'll likely be an edited one.

If possible, rebuilding the site (if you're using something like ant or phing) should make the problem go away so long as your source code hasn't been compromised. Of course you still need to work out how they did it in the first place.

Upvotes: 1

aleju
aleju

Reputation: 2386

If your stacktrace is always empty (and assuming you verified that correctly) then you may alternatively take a look at $_SERVER upon requests of your infected file. Maybe it isn't included by another php-file, e. g. called from the command line or is somehow directly requested.

file_put_contents('/tmp/debug.log', print_r($_SERVER, TRUE));

Especially take a look at the following values:

  • argv and REMOTE_ADDR (127.0.0.1?) to make sure that the script is not called over the command line.
  • REQUEST_URI, QUERY_STRING, SCRIPT_NAME and REQUEST_METHOD to find out from which URL your script gets called.
  • HTTP_REFERER to find out from where users come from that access your script (assuming that it is somehow called upon pageviews of your website).

Another option would be to use a recursive grep over all subdirectories of your website on your webserver to search for files that contain the name of the infected file:

grep -rl "your_infected_file.php" /path/to/your/website/folder

Upvotes: 3

Rolando Isidoro
Rolando Isidoro

Reputation: 5104

PHP's debug-backtrace function returns an array with the complete backtrace, you can use it like this is your offending backdoor/spambot .php files to figure out where they are being called:

file_put_contents('/tmp/debug.log', print_r(debug_backtrace(), TRUE));

Alternatively you can use the debug-print-backtrace function like this:

file_put_contents('/tmp/debug.log', debug_print_backtrace());

Upvotes: 1

rockerBOO
rockerBOO

Reputation: 3030

Using debug_backtrace, you will be able to see the require and include.

Upvotes: 1

Related Questions