Fedora Account System
Red Hat Associate
Red Hat Customer
AI_ONLY_REPORT package: rpm-6.0.1-5.1.hum1 ------ Summary: Code Execution via Macro Expansion of Manifest Entries in `rpmgi` (`-q -p` / verify manifest flows): attacker-controlled manifest entries are macro-expanded before open, allowing `%()` shell command execution in the caller context when non-package files are processed as manifests. Requirements to exploit: An attacker must supply a crafted manifest file and cause a user or automation to invoke `rpm -q -p` or a similar manifest-processing package-file flow on it without `--nomanifest`. No prior privileges are required beyond supplying the manifest; the resulting command executes with the privileges of the `rpm` process. Component affected: `rpm-6.0.1-5.1.hum1`, primarily `lib/rpmgi.cc` `rpmgiOpen()`, reached from manifest parsing in `lib/manifest.cc` during package-file query/verify handling. Version affected: `rpm-6.0.1-5.1.hum1` Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - 7.8 (HIGH) AV:L - Exploitation occurs through a local manifest file processed by the `rpm` CLI. AC:L - A single crafted manifest entry using RPM macro syntax is sufficient; no race or uncommon precondition is required. PR:N - The attacker does not need an account on the target system; delivering the crafted manifest is enough. UI:R - A user or automation must run an affected package-file query/verify flow on the attacker-controlled manifest. S:U - Exploitation affects the same security scope as the `rpm` process that parses the manifest. C:H - Successful command execution can read data available to the invoking context. I:H - Successful command execution can modify files or system state available to the invoking context. A:H - Successful command execution can disrupt or destroy data or service availability available to the invoking context. Impact: Important. This issue requires user-assisted processing of attacker-supplied manifest content, so it does not meet the criteria for Critical impact. However, once triggered it can execute arbitrary commands in the `rpm` caller context, which is sufficient to fully compromise confidentiality, integrity, and availability for that account. If the affected workflow is run by an administrator or privileged automation, the consequence is correspondingly severe. Embargo: no Reason: This is a user-assisted local CLI issue with a straightforward operational mitigation (`--nomanifest`) and no silent remote attack surface. Acknowledgement: Aisle Research Vulnerability Details: `rpm` package-file query handling constructs an `rpmgi` iterator for `-p` inputs. When the supplied file is not recognized as an RPM header, the iterator falls back to manifest handling. Manifest entries are read as plaintext strings and later reopened through `rpmgiOpen()`, which macro-expands the path before `Fopen()`: ```cpp static FD_t rpmgiOpen(const char * path, const char * fmode) { char * fn = rpmExpand(path, NULL); FD_t fd = Fopen(fn, fmode); if (fd == NULL || Ferror(fd)) { rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), fn, Fstrerror(fd)); if (fd != NULL) (void) Fclose(fd); fd = NULL; } free(fn); return fd; } ``` RPM macro expansion supports executable forms, including `%()` shell escapes. As a result, a manifest entry such as `%(id > /tmp/rpm_manifest_poc)` is evaluated before the open attempt, and the embedded command runs in the caller context. This is unexpected for `rpm-manifest(5)`, which documents manifests as plaintext glob/path entries naming RPM packages or other manifests rather than executable macro content. The concrete reproduction below demonstrates the issue in `-q -p`. Query and verify share the same package-file source handling around `rpmgi`, so manifest-processing verify flows should be treated as relevant as well, but the directly reproduced case here is query mode. Steps to reproduce: 1. Create a proof-of-concept manifest: ```bash cat > /tmp/poc.mft <<'EOF' %(id > /tmp/rpm_manifest_poc) EOF ``` 2. Run package-file query mode on the manifest: ```bash rpm -q -p /tmp/poc.mft ``` 3. Confirm the side effect: ```bash cat /tmp/rpm_manifest_poc ``` 4. A successful reproduction creates `/tmp/rpm_manifest_poc` containing the output of `id` from the invoking user context. 5. Control check: disable manifest processing and rerun: ```bash rpm -q -p --nomanifest /tmp/poc.mft ``` 6. With `--nomanifest`, the manifest should not be processed and the side-effect file should not be created by this invocation. Mitigation: Until a fix is available, do not run `rpm` package-file query or verify operations on untrusted manifest files. Use `--nomanifest` when handling untrusted inputs, and if manifest support is required in automation, pre-validate entries so that only expected literal paths or globs are accepted and macro syntax is rejected. Proposed Fix: Stop macro-expanding manifest-derived paths in `rpmgiOpen()` and open the original path string directly. ```diff diff --git a/lib/rpmgi.cc b/lib/rpmgi.cc — a/lib/rpmgi.cc +++ b/lib/rpmgi.cc @@ -49,8 +49,7 @@ static FD_t rpmgiOpen(const char * path, const char * fmode) { char * fn = rpmExpand(path, NULL); FD_t fd = Fopen(fn, fmode); + FD_t fd = Fopen(path, fmode); if (fd == NULL || Ferror(fd)) { rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), fn, Fstrerror(fd)); + rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), path, Fstrerror(fd)); if (fd != NULL) (void) Fclose(fd); fd = NULL; } free(fn); return fd; } ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use
Tracker filed for rhel-10.3: https://issues.redhat.com/browse/RHEL-189189