This is a personal blog. My other stuff: book | home page | Substack

October 24, 2014

PSA: don't run 'strings' on untrusted files (CVE-2014-8485)

Many shell users, and certainly most of the people working in computer forensics or other fields of information security, have a habit of running /usr/bin/strings on binary files originating from the Internet. Their understanding is that the tool simply scans the file for runs of printable characters and dumps them to stdout - something that is very unlikely to put you at any risk.

It is much less known that the Linux version of strings is an integral part of GNU binutils, a suite of tools that specializes in the manipulation of several dozen executable formats using a bundled library called libbfd. Other well-known utilities in that suite include objdump and readelf.

Perhaps simply by the virtue of being a part of that bundle, the strings utility tries to leverage the common libbfd infrastructure to detect supported executable formats and "optimize" the process by extracting text only from specific sections of the file. Unfortunately, the underlying library can be hardly described as safe: a quick pass with afl (and probably with any other competent fuzzer) quickly reveals a range of troubling and likely exploitable out-of-bounds crashes due to very limited range checking, say:

$ wget http://lcamtuf.coredump.cx/strings-bfd-badptr2
...
$ strings strings-bfd-badptr2
Segmentation fault
...
strings[24479]: segfault at 4141416d ip 0807a4e7 sp bf80ca60 error 4 in strings[8048000+9a000]
...
      while (--n_elt != 0)
        if ((++idx)->shdr->bfd_section)                                ← Read from an attacker-controlled pointer
          elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;  ← Write to an attacker-controlled pointer
...
(gdb) p idx->shdr
$1 = (Elf_Internal_Shdr *) 0x41414141

The 0x41414141 pointer being read and written by the code comes directly from that proof-of-concept file and can be freely modified by the attacker to try overwriting program control structures. Many Linux distributions ship strings without ASLR, making potential attacks easier and more reliable - a situation reminiscent of one of the recent bugs in bash.

Interestingly, the problems with the utility aren't exactly new; Tavis spotted the first signs of trouble some nine years ago.

In any case: the bottom line is that if you are used to running strings on random files, or depend on any libbfd-based tools for forensic purposes, you should probably change your habits. For strings specifically, invoking it with the -a parameter seems to inhibit the use of libbfd. Distro vendors may want to consider making the -a mode default, too.

PS. I actually had the libbfd fuzzing job running on this thing!

15 comments:

  1. Now, while `strings` is certainly the surprising tool, isn't this by extension infinitely more important for `objdump` which uses `libbfd` all over the place? I'd certainly think that the same group of people using `strings` for the described purpose use `objdump` for looking at disassembly, etc.

    ReplyDelete
  2. Sure, although objdump is a more niche tool (chiefly for forensics / RE), so the audience is a lot smaller.

    ReplyDelete
  3. I’d say if you’re actually using these tools to earn money, it is high time to go in and fix them. Also the linked bugs (nine years ago) is marked as fixed. Software has bugs. Free Software makes it possible for people who rely on it to fix the problems - especially when they rely on it for their profession. That’s part of the point of not making it non-commercial: To allow expert craftsmen to collaborate on improving their tools.

    ReplyDelete
  4. As you said, this is an already known but silent issue. A common workaround is to use "strings -a" to entirely avoid using libbfd.

    ReplyDelete
  5. Hi,
    I just made a test under slack64-14.1, freebsd64-10-P10, osx yosemite, and they all didn't report any problem.
    Output was always equal to:
    hello world
    .shstrtab
    .text
    .data
    AAAA

    but good to know =)

    ReplyDelete
    Replies
    1. At least on Slackware: strings is from util-linux; strings-GNU, from binutils crashes.

      Delete
  6. Luca,
    this is clearly expected, since all these operating systems use BSD string (that does not link to libbfd) instead of GNU string. The bug is specific to libbfd, not to some operating system.

    ReplyDelete
  7. Oh shit,

    It's not funny when you realize that that somebody is discovering priv8 0days.
    I've laughed a lot for a while targeting some white-hat biatches xDDDD. Here it
    goes another one related with PE file headers parsing ^_^ , indeed, I could say
    that there are tons of bugs related with binary parsing in binutils ]:-D

    $ strings /tmp/prueba.exe
    *** stack smashing detected ***: terminated
    ======= Backtrace: =========
    /usr/lib/libc.so.6(+0x7340e)[0x7f81ad08340e]
    /usr/lib/libc.so.6(__fortify_fail+0x37)[0x7f81ad108a97]
    /usr/lib/libc.so.6(__fortify_fail+0x0)[0x7f81ad108a60]
    /usr/lib/libbfd-2.24.so(+0xb79a2)[0x7f81ad46f9a2]
    ======= Memory map: ========
    00400000-00406000 r-xp 00000000 08:02 433688 /usr/bin/strings
    00605000-00606000 r--p 00005000 08:02 433688 /usr/bin/strings
    00606000-00607000 rw-p 00006000 08:02 433688 /usr/bin/strings
    020f5000-02137000 rw-p 00000000 00:00 0 [heap]
    [...]
    7f81ad6b5000-7f81ad6c7000 r--p 000fd000 08:02 436332 /usr/lib/libbfd-2.24.so
    7f81ad6c7000-7f81ad6cd000 rw-p 0010f000 08:02 436332 /usr/lib/libbfd-2.24.so
    7fffc1e5a000-7fffc1e7c000 rw-p 00000000 00:00 0 [stack]
    7fffc2000000-7fffc2002000 r-xp 00000000 00:00 0 [vdso]
    7fffc2002000-7fffc2004000 r--p 00000000 00:00 0 [vvar]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
    Abortado (`core' generado)


    Hey guys, do you wanna find something when fuzzing? Use as input the awesome
    radare2 regression tests https://github.com/radare/radare2-regressions.

    And for you MichaƂ, thanks for all you're work! Keep on it, maquina!

    Viva Andalucia Libre!

    ReplyDelete
  8. Is busybox strings vulnerable?

    ReplyDelete
    Replies
    1. Probably not, since they try to do the bare minimum; but please test if in doubt.

      Delete
  9. (sorry if this is a dup)

    I don't really care about the security implications, to me this is simply a mistake in strings. It is supposed to be a stupid utility, and in every case it is a disadvantage if it is smart. When I want a smart utility, I use objdump/nm/etc instead.

    The binutils maintainers are simply wrong, and a showing of community outrage is in order. Please send an irate email to binutils@sourceware.org. Thanks!

    ReplyDelete
  10. A partial, but quick and simple remedy is to alias 'strings' to 'strings -a'. That is, add this line to .bashrc

    alias strings='strings -a'

    ReplyDelete
  11. If you're using a recent release of the GNU binutils version of the strings command, this problem is already solved. It defaults to "-a", which scans the entire file and doesn't use the BFD library. This change was made in 2014 and first appeared in binutils 2.26.

    Here's the git commit:
    https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=7fac9594c41ab180979bdf5927ff7f7e1d13a9e9

    ReplyDelete

Note: Only a member of this blog may post a comment.