Talos Vulnerability Report

TALOS-2016-0057

Libgraphite Bidirectional Font BracketPairStack Code Execution Vulnerability

February 5, 2016

Report ID

CVE-2016-1522

Description

An exploitable out-of-bounds access vulnerability exists in the bidirectional font handling functionality of Libgraphite. A specially crafted font can cause an out-of-bounds access resulting in arbitrary code execution. An attacker can provide a malicious font to trigger this vulnerability.

Tested Versions

Libgraphite 2-1.2.4

Product URLs

http://sourceforge.net/projects/silgraphite/files/graphite2/

Details

In Segment.cpp at line 469 in the function Segment::bidiPass, the variable ssize is initialized to 0 at line 455 and will increase in size depending on attributes that are read from the font at lines 456-466. However if those attributes aren’t set, then ssize will remain 0 when a new BracketPairStack is allocated at line 469.

unsigned int ssize = 0;
for (s = first(); s; s = s->next())
{
	if (s->getBidiClass() == -1) {
		unsigned int bAttr = glyphAttr(s->gid(), aBidi);
		 s->setBidiClass((bAttr <= 22) * bAttr);
	}
	bmask |= (1 << s->getBidiClass());
	s->setBidiLevel(baseLevel);
	if (glyphAttr(s->gid(), aMirror) && s->getBidiClass() == 21)
	++ssize;
}

BracketPairStack bstack(ssize);

This will cause the constructor of BracketPairStack to call grzeroallocsize with the size provided to allocate the stack. This in turns calls calloc with the size of the BracketPair object and the provided size. On a 64-bit machine, this will result in calloc(0,48). This will result in the smallest size chunk being allocated and zeroed-out. On a 64-bit machine that is 32-bytes. Since the resulting stack is expected to be at least 48 bytes, an out-of-bounds access on the heap memory will occur when trying to use BrackPairStack’s stack.

When the stack is used, BracketPairs will be read from the stack and will be walked using their next pointer until a NULL pointer is reached. An example of this can be seen at line at line 574 in the function ProcessParens in the file Bidi.cpp:

for (p = stack.start(); p; p =p->next()) // walk the stack

In the case of the sample provided here, the next pointer is corrupted because it hasn’t been initialized to 0, because it is read from outside the bounds of the BracketPairStack object. If an attacker controls the memory behind the BracketPairStack, this can result in arbitrary code execution.

The malicious font provided here can be used to generate the problem by using the ‘simple’ test program provided with libgraphite and the parameter ‘test’: ./simple maliciousfont test

Credit

Discovered by Yves Younan of Cisco Talos.