Support of %n in printf
Format strings vulnerabilities are a great
way
to get arbitrary read-write. A straight-forward mitigation for this one would
be to remove support for %n
, turning format string issues from arbitrary r/w
into arbitrary read. An extra precaution, to remove the read capabilities, is
to compile with -Wformat=2
,
checking for fishy usages of printf
and its friends.
User-land
Support for %n
was
disabled by default in Visual Studio 2005
on Windows, and Android never supported it despite being based on OpenBSD’s libc.
In August 2013, Ted Unangst, OpenBSD developer, explained that OpenBSD doesn’t follow some parts of the POSIX specifications, on purpose.
In October 2014, Theo de Raadt also advocated for breaking strict POSIX conformance, because it made sense to do so.
But, in May 2014, while Theo de Raadt added the
possibility to disable
support for the infamous %n
specifier at compilation time, this feature still
isn’t enabled by default. It was added because the Android people asked for
it, and the argument against simply removing support for %n
is that OpenBSD
is fully standardized.
This resulted in OpenBSD shipping software with format string:
- relayd and iscsid in 2017
Starting with OpenBSD 7.0,
printf(3)
and friends now log an error and abort when confronted with format %n
.
Kernel-land
A first patch to remove %n
from Linux’ printk
was
proposed in March 2004 by
Muli Ben-Yehuda.
It was removed in April and November 2014, by Kees Kook, and Ryan Mallon based on the previous work of Joe Perches.
In November 2013, djm disabled %n
in
printf(9)
in OpenBSD, inspired from
Kees Cook’s work.