Lucene search

K
talosTalos IntelligenceTALOS-2016-0227
HistoryMar 09, 2017 - 12:00 a.m.

R PDF LoadEncoding Code Execution Vulnerability

2017-03-0900:00:00
Talos Intelligence
www.talosintelligence.com
31

CVSS2

6.8

Attack Vector

NETWORK

Attack Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

CVSS3

8.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

EPSS

0.002

Percentile

58.7%

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/&gt;

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 &lt; 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

CVSS2

6.8

Attack Vector

NETWORK

Attack Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

CVSS3

8.8

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

EPSS

0.002

Percentile

58.7%