https://bugs.kde.org/show_bug.cgi?id=523068

            Bug ID: 523068
           Summary: Valgrind PDB File Search Command Injection via Crafted
                    PE Path
    Classification: Developer tools
           Product: valgrind
      Version First unspecified
       Reported In:
          Platform: Other
                OS: All
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: general
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

Created attachment 194307
  --> https://bugs.kde.org/attachment.cgi?id=194307&action=edit
poc

# Valgrind PDB File Search Command Injection via Crafted PE Path

**Product:** Valgrind
**Version:** 3.27.1 (latest release)
**File:** `coregrind/m_debuginfo/readpdb.c`
**Function:** `ML_(find_name_of_pdb_file)` (line 2529-2534)
**CWE:** CWE-78 (Improper Neutralization of Special Elements used in an OS
Command)
**CVSS 3.1:** 7.8 (AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)
**Auth Required:** None (user runs PE executable under Valgrind + Wine)
**Validation: Lab verified**
**Environment:** Valgrind 3.27.1 source (valgrind-3.27.1.tar.bz2), Linux with
Wine, default build configuration
**Commit:** HEAD at sourceware.org/git/valgrind.git (verified 2026-07-01)

## Summary

When Valgrind processes a Windows PE executable (via Wine on Linux), it invokes
`strings` and `grep` via `VG_(system)` (which calls `/bin/sh -c <cmd>`) to
locate the associated PDB debug file. The PE filename is placed in single
quotes inside a double-quoted shell command, but in POSIX shell, single quotes
inside double quotes are literal characters and provide no quoting protection.
`$()` command substitution and backtick expansion remain active.

## Vulnerable Code

`coregrind/m_debuginfo/readpdb.c`, lines 2520-2534:

```c
const HChar* sh      = "/bin/sh";
const HChar* strings = "strings";
const HChar* egrep   = "grep -E";

/* (sh) -c "(strings) (pename) | (egrep) 'pdb' > (tmpname) */
Int cmdlen = VG_(strlen)(strings) + VG_(strlen)(pename)
             + VG_(strlen)(egrep) + VG_(strlen)(tmpname)
             + 100/*misc*/;
HChar* cmd = ML_(dinfo_zalloc)("di.readpe.fnopf.cmd", cmdlen);
VG_(sprintf)(cmd, "%s -c \"%s '%s' | %s '\\.pdb$|\\.PDB$' >> %s\"",
                  sh, strings, pename, egrep, tmpname);
                              // ^^^ unsanitized PE filename
vg_assert(cmd[cmdlen-1] == 0);

r = VG_(system)( cmd );      // <-- executes via /bin/sh -c
```

The resulting shell command is:
```
/bin/sh -c "strings '<PE_FILENAME>' | grep -E '\.pdb$|\.PDB$' >>
/tmp/vg_pdb_xxx"
```

In POSIX shell, single quotes inside double quotes are literal characters. The
`pename` is effectively unquoted within the double-quoted `-c` argument, so
`$()` and backtick substitution are expanded.

## Data Flow

1. User runs `valgrind wine ./program.exe` on Linux
2. Wine loads the PE executable; Valgrind intercepts and processes its debug
information
3. `ML_(find_name_of_pdb_file)` is called with the PE filename as `pename`
4. Line 2529: `VG_(sprintf)` constructs a shell command embedding `pename` in
single quotes inside double quotes
5. Line 2534: `VG_(system)(cmd)` invokes `/bin/sh -c "<command>"`
6. Shell expands any `$()` or backtick sequences in the PE filename

## Attack Model

An attacker provides a PE executable at a path containing shell metacharacters:

```
/tmp/prog$(touch${IFS}/tmp/pwned).exe
```

When run under Valgrind + Wine:

1. Valgrind processes the PE file's debug information
2. `ML_(find_name_of_pdb_file)` constructs:
   `/bin/sh -c "strings '/tmp/prog$(touch${IFS}/tmp/pwned).exe' | grep -E
'\.pdb$|\.PDB$' >> /tmp/vg_pdb_xxx"`
3. The single quotes provide no protection inside the `"..."` argument to
`/bin/sh -c`
4. Shell expands `$(touch${IFS}/tmp/pwned)` -- arbitrary command execution

**Vectors:**
- CTF challenges or untrusted Windows binaries analyzed with Valgrind + Wine
- Malware analysis workflows where PE samples are examined under Valgrind for
memory error detection
- Shared analysis directories where filenames are attacker-controlled

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to