| Название | webgjc web_robot 2.8.0 OS Command Injection |
|---|
| Описание | A vulnerability has been identified in webgjc web_robot, a browser-automation tool ("网页自动化插件")
that consists of a Chrome extension plus a local Python/Flask backend service (py/web.py) which the
extension and web pages drive over HTTP. The service is started with "python py/web.py" and binds to
127.0.0.1:12580. The issue is an unauthenticated OS command injection (CWE-78) leading to arbitrary
command execution as the user running the service.
AFFECTED CODE
The GET endpoints /record/ (function controller_listen) and /recover/ (function controller_recover) in
py/web.py read the "case_name" query parameter and concatenate it, unescaped, into an os.system() call:
case_name = request.args.get('case_name')
os.system(PYTHON_ENV + " py/controller.py record " + case_name + " 2>&1 &")
(/recover/ uses the identical pattern with the "recover" verb.) Because os.system() executes its
argument through /bin/sh -c, any shell metacharacter in case_name (; | & $() ``) breaks out of the
intended command and executes attacker-supplied commands. The "./venv/bin/python" prefix failing is
irrelevant: the ";" characters split the string into independent shell commands, so the payload runs
regardless of whether the wrapped script exists.
ROOT CAUSE
The application performs no authentication, no input validation/sanitization, and no CSRF/Origin
verification on any endpoint (verified across the entire py/ tree). User input flows directly from an
HTTP request parameter into a shell.
AFFECTED VERSIONS
The vulnerable sink was introduced in commit f0b0f8a (2020-06-04) and is present verbatim in every
tagged release (2.4.0, 2.5.0, 2.8.0) and in current master HEAD (commit 595a7e4, 2023-09-11). No fixed
version exists; the project has been unmaintained since 2023. All 18 forks carry byte-identical
vulnerable code.
PROOF OF CONCEPT
curl -G 'http://127.0.0.1:12580/record/' --data-urlencode 'case_name=;id>/tmp/pwned;'
cat /tmp/pwned # -> uid=... gid=... (the injected `id` executed)
Replacing `id` with any command (reverse shell, credential exfiltration, etc.) yields full control.
IMPACT
Arbitrary OS command execution with the privileges of the user running web_robot: full local compromise
(reverse shell, theft of SSH keys / browser session tokens / cloud credentials, persistence, lateral
movement). The core defect is browser-independent - any local HTTP client that reaches 127.0.0.1:12580
(a co-resident process, another local user, a script) obtains code execution with a single
unauthenticated request.
BROWSER DELIVERY (drive-by)
Because the service is a browser companion with no auth and no CSRF/Origin check, a web page the victim
opens can issue a cross-origin GET to it (e.g. an <img> with src
http://127.0.0.1:12580/record/?case_name=;cmd;); the server executes the command regardless of the
opaque response. Honest scope: on current default Chrome (142+) and Firefox (150+), a public-origin
page reaching 127.0.0.1 is gated behind a Local Network Access permission prompt, and DNS rebinding
does not bypass LNA. The silent zero-click drive-by therefore holds on Safari, older Chromium/Firefox,
local-origin/same-address-space pages, and enterprise fleets with LNA disabled; on fully updated
browsers it degrades to a one-click "Allow local network access" prompt.
CVSS
Headline: 7.5 (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H). Conditional: 8.8 on non-LNA browsers /
local-origin contexts (AC:L); 8.4 for a co-resident local process (AV:L/UI:N); 9.8 if the listener is
rebound to x.x.x.x (UI:N).
SECONDARY WEAKNESSES (defense-in-depth, not part of the primary claim)
- /crawler/ has an unauthenticated path traversal (CWE-22): write/delete/read via an unsanitized
case_name.
- py/controller.py contains eval(record.get('key'), {}, {}) (CWE-95); RCE-capable but only reachable
via a redundant path-traversal chain that terminates in the same os.system sink.
- The service runs with Flask debug=True (CWE-489).
state-changing actions POST-only with a CSRF token), sanitize case_name against path traversal in
/crawler/, and set debug=False.
DISCLOSURE
Vendor notified privately; project appears unmaintained since 2023. Coordinated disclosure. Discovered
by Mario Madersbacher (GitHub: mmadersbacher). |
|---|
| Источник | ⚠️ https://github.com/webgjc/web_robot/blob/595a7e4634e62c482ad15d814b56bb25403f9cc0/py/web.py#L26-L36 |
|---|
| Пользователь | Telqrrr (UID 99828) |
|---|
| Представление | 15.07.2026 23:15 (2 месяцы назад) |
|---|
| Модерация | 12.09.2026 10:04 (2 months later) |
|---|
| Статус | принято |
|---|
| Запись VulDB | 403080 [webgjc web_robot 2.4.0/2.5.0/2.8.0 py/web.py controller_listen/controller_recover case_name эскалация привилегий] |
|---|
| Баллы | 20 |
|---|