### Summary
An exploitable buffer overflow vulnerability exists in the LoadEncoding functionality of the R programming language version 3.3.0. A specially crafted R script can cause a buffer overflow resulting in a memory corruption. An attacker can send a malicious R script to trigger this vulnerability.
### Tested Versions
R 3.3.0
R 3.3.2
### Product URLs
https://www.r-project.org/
### CVSSv3 Score
7.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
### Details
The R programming language is commonly used in statistical computing and supported by the R Foundation for Statistical Computing. R is praised for having a large variety of statistical and graphical features.
During the creation of a PDF document, the file containing the encoding array can be specified by the user. The following command can specify the encoding file for a pdf.
```
pdf(encoding="/path/to/some/file")
```
While loading this file, each of the specific elements in the file is copied into the `cname` element for each item in the `encnames` array [0].
```
src/library/grDevices/src/devPS.c:493
LoadEncoding(const char *encpath, char *encname,
char *encconvname, CNAME *encnames,
char *enccode, Rboolean isPDF)
{
...
for(i = 0; i < 256; i++) {
if (GetNextItem(fp, buf, i, &state)) {
fclose(fp); return 0;
}
strcpy(encnames[i].cname, buf+1); // [0]
strcat(enccode, " /"); strcat(enccode, encnames[i].cname);
if(i%8 == 7) strcat(enccode, "\n");
}
...
```
The `encnames` array is a part of a `EncodingInfo` structure.
```
/*
* Information about a font encoding
*/
typedef struct EncInfo {
char encpath[PATH_MAX];
char name[100]; /* Name written to PostScript/PDF file */
char convname[50]; /* Name used in mbcsToSbcs() with iconv() */
CNAME encnames[256];
char enccode[5000];
} EncodingInfo, *encodinginfo;
```
The `encnames` array is of structure type `CNAME` with a `cname` attribute that is a buffer of length 40 [1].
```
src/library/grDevices/src/devPS.c:281
/* The longest named Adobe glyph is 39 chars:
whitediamondcontainingblacksmalldiamond
*/
typedef struct {
char cname[40]; // [1]
} CNAME;
```
By providing an element in the encoding file of longer than length 40, the `cname` buffer is overflown. This could be leveraged to potentially gain remote code execution later in the program.
### Crash Information
```
$ R -d valgrind -f poc.r
...
==21442== Invalid write of size 1
==21442== at 0x4C34140: __stpcpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21442== by 0xA0D4D89: ??? (in /usr/lib/R/library/grDevices/libs/grDevices.so)
==21442== by 0xA0D6A5B: ??? (in /usr/lib/R/library/grDevices/libs/grDevices.so)
==21442== by 0xA0E226D: PDFDeviceDriver (in /usr/lib/R/library/grDevices/libs/grDevices.so)
==21442== by 0xA0E3DE9: PDF (in /usr/lib/R/library/grDevices/libs/grDevices.so)
==21442== by 0x4F08F80: ??? (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F34BFC: ??? (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F40F2F: Rf_eval (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F4296D: Rf_applyClosure (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F410CC: Rf_eval (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F68891: Rf_ReplIteration (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F68C10: ??? (in /usr/lib/R/lib/libR.so)
==21442== Address 0x79f5eee is 0 bytes after a block of size 19,486 alloc'd
==21442== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21442== by 0xA0D6A28: ??? (in /usr/lib/R/library/grDevices/libs/grDevices.so)
==21442== by 0xA0E226D: PDFDeviceDriver (in /usr/lib/R/library/grDevices/libs/grDevices.so)
==21442== by 0xA0E3DE9: PDF (in /usr/lib/R/library/grDevices/libs/grDevices.so)
==21442== by 0x4F08F80: ??? (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F34BFC: ??? (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F40F2F: Rf_eval (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F4296D: Rf_applyClosure (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F410CC: Rf_eval (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F68891: Rf_ReplIteration (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F68C10: ??? (in /usr/lib/R/lib/libR.so)
==21442== by 0x4F68CC3: run_Rmainloop (in /usr/lib/R/lib/libR.so)
```
### Timeline
* 2016-11-17 - Vendor Disclosure
* 2017-03-09 - Public Release
### CREDIT
* Discovered by Cory Duplantis of Cisco Talos
暂无评论