Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 29 Apr 2024 11:46:21 +0200
From: Vegard Nossum <>
Cc: Hank Leininger <>, Jacob Bachmeyer <>
Subject: Re: Update on the distro-backdoor-scanner effort

On 28/04/2024 08:34, Hank Leininger wrote:
> On 2024-04-27, Jacob Bachmeyer wrote:
>>> - Check for irregular contents in .pc files, inspired by Vegard 
>>> Nossum's oss-security post
>> Much easier:  look for pkg-config descriptions containing text
>> other than a variable definition.  The pkg-config tool itself
>> should probably enforce "cleanliness" on this matter and refuse to
>> process files containing other text.  (It also should complain
>> about and reject an *-uninstalled.pc file found in the system
>> directories, which was another logic error exploited in that sample
>> backdoor.)
> Really, doing this seems a more robust approach anyway, because
> allowing only known-good > rejecting known-bad. I was mostly driven
> by "hang on, how many of the things Nossum's example does are
> actually used by real files?" and the answer from my initial sample
> size was zero, so it'd be trivial to extend that check to every .pc
> file shipped by every current distro's packages.
> I think Sam looked into existing pkg-config verifiers and found they
> do not complain about things we thought they should complain about
> (this could just mean we misunderstand their purpose). A strict
> lint-checker for such files would be better than just checking for
> specific suspicious patterns. But, I don't yet know how strict a
> format we could insist on (would it turn out 10% of files in fact
> break what we initially think are reasonable rules?). Even still, I
> think you could embed badness in legit variables, although I haven't
> dug in enough to know that for sure.


Masquerading a shell command as a pkg-config variable definition is
trivial (but probably still detectable) since you can just do:

foobar=/usr echo hi

which AFAIK is a valid pkg-config variable definition but also a valid
shell command.

Also remember that in my particular example I reused the same file but
it would also be trivial to use a different file in the $(...) expansion
so that the payload actually lives somewhere else. The payload doesn't
even have to be a shell script, it could also be a small ELF binary or
something where you wouldn't necessarily be able to tell at a glance
that it does something malicious.

So probably the real thing to look for would be $(...) in pkg-config
files -- Hank, you mentioned in the GitHub issue that you did fine this
in one file; out of curiosity, could you share it?

I tried this on my system and didn't find anything:

$ grep -R '\$(' /usr/share/pkgconfig /usr/lib/x86_64-linux-gnu/pkgconfig

It's also worth asking if there are other ways to encode that $() that
bypasses the very simple '\$(' pattern -- e.g. something like "$\(" or
maybe an expansion of a variable that itself contains the $ character:

$ cat test.pc

Name: test
Version: 0
Cflags: ${foo}(echo hi)

$ PKG_CONFIG_PATH=. pkg-config --cflags test
$(echo hi)

There are also other ways to achieve the same effect.

I should also add that I found out-of-bounds memory accesses in both the
original pkg-config and pkgconf (used on Debian and RedHat derivatives,
respectively, AFAIK) when using long variable names -- it doesn't look
exploitable to me but I've submitted some patches for both packages just
in case.



Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.