Buffer overflow vulnerability in PS_options() – gnuplot 5.2.5
Loginsoft-2018-17974
November 2, 2018
CWE
CWE-120: Classic Buffer Overflow
Product Details
Gnuplot is a portable command-line driven graphing utility.
URL: https://sourceforge.net/projects/gnuplot/
Vulnerable Versions
5.2.5 branch
Vulnerability Details
During our research on the gnuplot, we found buffer overflow vulnerability. This can be triggered by sending a crafted file to gnuplot. This allows an attacker to cause Denial of Service (Segmentation fault and Memory Corruption) or possibly have unspecified other impacts when a victim opens a specially crafted file.
SYNOPSIS
In our research we found that in function PS_options()
in program post.trm, There exists an condition if (ps_params->oldstyle)
where the value of ps_params->oldstyle
is zero and makes the program enter to the else section, where it calls sprintf()
as we observed the basic syntax of sprintf()
in this program is sprintf(BUFFERSIZE,char,int)
. PS_default_font
consists of a buffer value of 51. When a crafted input file is sent to the binary, we observed that ps_params->font
had a size of 51 and ps_fontsize
with size 14. Which buffer size of both ps_params->font
ps_fontsize
together is larger than the allocated buffer in PS_default_font
which triggered a buffer overflow vulnerability.
Analysis
if (ps_params->oldstyle) term->h_char = (unsigned int)(ps_fontsize*PS_SCF*5/10); else term->h_char = (unsigned int)(ps_fontsize*PS_SCF*6/10); sprintf(PS_default_font,"%s,%.2g",ps_params->font,ps_fontsize);
gef➤ p __sprintf $37 = {int (char *, const char *, ...)} 0x7ffff7555940 gef➤ ptype PS_default_font type = char [51] gef➤ p ps_fontsize $38 = 14 gef➤ p/d ps_params->font $39 = {99, 111, 105, 116, 108, 101, 100, 97, 115, 119, 101, 100, 45, 108, 119, 45, 49, 45, 34, 68, 101, 95, 97, 86, 117, 83, 97, 115, 116, 115, 99, 114, 105, 112, 116, 115, 101, 116, 45, 111, 117, 116, 112, 82, 116, 45, 34, 116, 101, 109, 0} gef➤ ptype ps_params type = struct ps_params_t { enum PS_TERMINALTYPE terminal; int xoff; int yoff; enum PS_PSFORMAT psformat; _Bool level1; _Bool level3; _Bool color; _Bool blacktext; _Bool solid; float dash_length; float linewidth_factor; float pointscale_factor; _Bool duplex_option; _Bool duplex_state; _Bool rounded; _Bool clipped; struct ps_fontfile_def *first_fontfile; char font[51]; float fontsize; float fontscale; _Bool useauxfile; _Bool rotate; int palfunc_samples; double palfunc_deviation; _Bool oldstyle; _Bool epslatex_standalone; _Bool adobeglyphnames; rgb_color background; } *
ASAN Output
==21975== Memcheck, a memory error detector ==21975== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==21975== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==21975== Command: gnuplot -d -c /home/aceteam/POC ==21975== set term postscript port enhanced'coitledaswed lw 1 "De_aVuSastscriptset outpRt "tempNps"' ^ *** buffer overflow detected ***: gnuplot terminated ==21975== ==21975== Process terminating with default action of signal 6 (SIGABRT) ==21975== at 0x562AE97: raise (raise.c:51) ==21975== by 0x562C800: abort (abort.c:79) ==21975== by 0x5675896: __libc_message (libc_fatal.c:181) ==21975== by 0x5720CFE: __fortify_fail_abort (fortify_fail.c:33) ==21975== by 0x5720D20: __fortify_fail (fortify_fail.c:44) ==21975== by 0x571EA0F: __chk_fail (chk_fail.c:28) ==21975== by 0x571DF28: _IO_str_chk_overflow (vsprintf_chk.c:31) ==21975== by 0x567A493: _IO_default_xsputn (genops.c:417) ==21975== by 0x56479A9: vfprintf (vfprintf.c:1674) ==21975== by 0x571DFCA: __vsprintf_chk (vsprintf_chk.c:82) ==21975== by 0x571DEF9: __sprintf_chk (sprintf_chk.c:31) ==21975== by 0x4ACEBC: sprintf (stdio2.h:33) ==21975== by 0x4ACEBC: PS_options (post.trm:1197) ==21975== ==21975== HEAP SUMMARY: ==21975== in use at exit: 27,001 bytes in 144 blocks ==21975== total heap usage: 230 allocs, 86 frees, 160,952 bytes allocated ==21975== ==21975== LEAK SUMMARY: ==21975== definitely lost: 0 bytes in 0 blocks ==21975== indirectly lost: 0 bytes in 0 blocks ==21975== possibly lost: 0 bytes in 0 blocks ==21975== still reachable: 27,001 bytes in 144 blocks ==21975== suppressed: 0 bytes in 0 blocks ==21975== Rerun with --leak-check=full to see details of leaked memory ==21975== ==21975== For counts of detected and suppressed errors, rerun with: -v ==21975== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Aborted
Proof of Concept
gnuplot -d –c $POC
Timeline
Vendor Disclosure: 2018-11-02
Public Disclosure: 2018-11-03
Credit
Discovered by ACE Team – Loginsoft