%n !!

S

Spiros Bousbouras

No problem, I have no desire to argue words. If you don't consider
that example to be an example of what you were asking for, then so be
it. The example can turn from a bad idea into a tolerable one by a
simple scan of the format and a call to exit if anything odd is seen.
Does that suit your definition of useful?

It does but then the user input is not used as given but
precautions are made. That's fine. A programmer who
does that won't have anything to gain by having to call
an extra function in order to be able to use %n.
 
H

Harald van Dijk

If it's a translation it's not the same thing at all. A translation can
make it safe.

Yes, the _ function can check that the format specifiers of the
translated string match those of its argument, but that's not something
the compiler or printf knows about. To printf, it will be just as much a
user-specified string as argv[1].
 
N

Nate Eldredge

Spiros Bousbouras said:
Who is the user in this case , the programme calling syslog() ?

The typical example is a daemon which provides some service to people
who connect over the network. The daemon might want to log some of the
data it receives from the remote user.
"Safer", not "safe". I think without %n, there's a lot less harm an
attacker can do. Did you have something specific in mind?

I had in mind unterminated strings causing DOS or crashes,
strings with other specifiers apart from %n and even
printf("%s",user_supplied_string) is not safe. What happens if
the string contains control characters ? It could mess up the
display and more specifically cause information a cracker does
not want to be seen to not appear [1]. I also wonder if there have
been terminals which could be made to explode with the right
sequence of control characters.

I see. Another sort of exploit is to send the terminal a control
sequence which remaps, say, the Enter key, to insert some other text
(e.g. "; rm -rf /").

That's certainly a concern, but it's mitigated in logfile-type
situations where the data is sent to a file, and is viewed with a viewer
that handles control characters specially.
Then there's also this:

From http://www.azillionmonkeys.com/windoze/analysis_windoze.html
While its no surprise that Windows has bugs in it, simply
sending too many backspaces to it appears to send the NT
kernel (read: NT, 2K, XP) into a blue screen of death, followed
by a spontaneous reboot.

That was fixed in 2002. And it too would be avoided by viewing the file
with some other application.
In view of all the above , making harder to use %n seems a drop
in an ocean. Furthermore a programmer who doesn't realise the
above dangers will activate %n when they need it and happily
forget about it. There goes your increase in safety.

Certainly it's debatable. But I'm not sure there's value in debating it
any further, since we seem to have made up our minds, and Microsoft
won't listen to either of us anyway :)
 
C

CBFalconer

Spiros said:
.... snip ...

I doubt that it makes the world a safer place. Even if all the
users were angels and even if %n didn't exist there are still
many things that can go wrong with arbitrary printf() format
strings. If a programmer doesn't realise that and takes measures
to deal with it then the lack of default inclusion of %n isn't
going to save them.

I agree. A safe replacement for printf would not be a variadic
function at all (and thus far from an exact replacement). This
might require a fairly large collection of dedicated routines, but
those not used need not be loaded (which is not the situation with
the present system). Others will argue that such a large loading
is avoided by the use of common library code, in a dll for Windows,
or other shared executable formats. However, that only applies to
some systems. And such reduction would still be available.
 
P

Phil Carmody

Kenneth Brody said:
karthikbalaguru said:
karthikbalaguru said: [...]
printf( "ABC %n Ok\n", &a );
[...]
I use Visual C++ 2008 Express edition.
[...]

This is from the VS2008 documentation on printf() format specifiers:

Security Note The %n format is inherently insecure and is disabled
by default; if %n is encountered in a format string, the invalid
parameter handler is invoked as described in Parameter Validation.
To enable %n support, see _set_printf_count_output.

%n is barely less secure than %s. OK, one could performs a write
to an arbitrary location, the other only performs a read from an
arbitrary location, but both are breaking out of the sandbox that
any sensible programmer would be working in.

This seems like Microsoft simply admitting that most people who
program for their OSes are idiots.

Phil
 
K

Keith Thompson

Phil Carmody said:
%n is barely less secure than %s. OK, one could performs a write
to an arbitrary location, the other only performs a read from an
arbitrary location, but both are breaking out of the sandbox that
any sensible programmer would be working in.
[...]

How is %n less secure than %s? If used properly, %n is perfectly
safe; just pass the address of a writable integer object. %s can't be
used safely unless you can control what will appear on stdin.
 
R

Richard Tobin

%n is barely less secure than %s. OK, one could performs a write
to an arbitrary location, the other only performs a read from an
arbitrary location, but both are breaking out of the sandbox that
any sensible programmer would be working in.
[/QUOTE]
How is %n less secure than %s? If used properly, %n is perfectly
safe; just pass the address of a writable integer object. %s can't be
used safely unless you can control what will appear on stdin.

We're talking about printf(), not scanf(). If the user can control
the format string, %s could conceivably be used to reveal the contents
of memory that should be secret, though it would be tricky to say the
least.

-- Richard
 
I

Ike Naar

How is %n less secure than %s? If used properly, %n is perfectly
safe; just pass the address of a writable integer object. %s can't be
used safely unless you can control what will appear on stdin.

If used improperly, %n can allow an attacker to modify a program variable.

For instance, the program below contains a supposedly readonly string, s.
The string is to be printed in a format that is under the control
of the user.
A benevolent user may supply goodformat.
A malicious user may supply evilformat, changing the value of the string.

#include <stdio.h>
int main(void)
{
char const s[] = "Hello";
char const *goodformat = "I say: %s!\n";
char const *evilformat = "I say: Hello! "
" "
" \n%n";
printf(goodformat, s);
fprintf(stderr, "debug:s=\"%s\"\n", s);
printf(evilformat, s);
fprintf(stderr, "debug:s=\"%s\"\n", s);
return 0;
}

stdout:
I say: Hello!
I say: Hello!

stderr:
debug:s="Hello"
debug:s="A"
 
K

Kaz Kylheku

Kenneth Brody said:

This is absolutely the wrong solution. What they need is a compiler
switch.

You can probably put the _setf_printf_count output into a separate
translation unit, where it is invoked from some global constructor hook.
Then you have a link-time switch: add that unit, or not.
 
M

Mark Wooding

Nate Eldredge said:
On Unix, this issue commonly arises with the syslog(3) function, where
the only way to log a string uses printf-type format specifiers; there's
no equivalent to `fputs' that one might use instead.

Huh?

syslog(LOG_MUMBLE, "%s", my_string);
"Safer", not "safe". I think without %n, there's a lot less harm an
attacker can do. Did you have something specific in mind?

Off the top of my head, a carefully chosen field width might overwrite
security-critical data, e.g., counters, passwords, heap metadata. A use
of %s or %lx after eating sufficiently many arguments might leak
secrets.

-- [mdw]
 
N

Nate Eldredge

Mark Wooding said:
Huh?

syslog(LOG_MUMBLE, "%s", my_string);

Sure. What I'm saying is that, since there isn't a *function*
equivalent to fputs, the programmer might not be in the mindset that
there is another way to handle strings which aren't supposed to contain
formatting.
Off the top of my head, a carefully chosen field width might overwrite
security-critical data, e.g., counters, passwords, heap metadata.

For sprintf, sure, but in that case you might be able to just make the
string itself really long. I don't see how this applies with something
like fprintf that writes to a file; am I missing something?
A use
of %s or %lx after eating sufficiently many arguments might leak
secrets.

True.
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kenneth said:
karthikbalaguru said:
karthikbalaguru said: [...]
printf( "ABC %n Ok\n", &a );
[...]
I use Visual C++ 2008 Express edition.
[...]

This is from the VS2008 documentation on printf() format specifiers:

Security Note The %n format is inherently insecure and is disabled
by default; if %n is encountered in a format string, the invalid
parameter handler is invoked as described in Parameter Validation.
To enable %n support, see _set_printf_count_output.

It is not by any means inherently insecure. It is insecure if and only
if you do silly things like allow the format string to be from an
untrusted source or pass the wrong arguments to printf(). Trust it to
Microsoft to completely miss the point on security issues.

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJrDKsAAoJEKmxP9YxEE4r4UYQAMjBSzvSYn8x2OyWYIMJZ8XJ
P+DY8cbPGl4Ri8P8ogPId4/mY2MkHdgHj+IBXZcOMEqJf/FZae5k1992MzP94T55
MY/KKed9whN8f29Yvo+EsGR5fUSOJKSWoxB9j5Cq86SJXQgCRYYxvDcrmR7l3RGS
rlFe9UivgVEK8APlFEFMqBxHpf+8xewpGInRIepgxSKO5hFU8zPvPmto2T2zfhWI
VtjcmxcXjQeUcpGg1fX2Dv7sE51aVQFsA5NPEVlbwpTzplkrn2KCcWudboScljV/
kHz+VM3cc4l5Mbvjzlj+1H5gIwF7qq7Gw3u/V2cWQqS9Xcs4eaui4nJRQyfWW7Hc
lvIxtdwYxBlGZQ+7zVftTtJEAs5ZhZQUh2JpnKhjcU9HneyPtiSpNJ+0jknbcN1I
uUFq6ymVD17z6d1qdhyUTs5WiekbwjD5O7seGheiWAYEKm5knO2eZc86vHmvXjd+
k3WMoPZgO4mMY/0JuXqxoJ0Vl75lP8FBqxIDgaPuwyLTac3h6LVgYt4yyHoZ36Fa
BM3qgWfSHYBoyikOnalfVaOowR8XSQC7aBZ5JaWf9ytDWqUd0nK5MOpMJNDI/56q
H4BqYK4WDXTCF1anS7uZQuu0iTS6ARFGJGY7A84jRAbLRgi0CygAQO7Mc7wOX6O2
/sYaKboflFFM/Y8gghuL
=OeIR
-----END PGP SIGNATURE-----
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Richard said:
Nate Eldredge said:



If so, it's a feature that breaks ISO conformance and, at least in
theory, portability to MS platforms. In practice, however, nobody
actually uses %n, do they?

<snip>

One extremely practical use would be if you were writing a file that had
headers of some kind to delimit field widths, instead of using a
delimiter character. However, this is the only use I can think of at
the moment, and that is something rarely done for text.

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIbBAEBAgAGBQJJrDRcAAoJEKmxP9YxEE4ruSAP90nzPtNUTG3BLwGYa6jmQNSl
AQfEft7i9yS1uzrWOiXOlRoxQTjl+xF1gd0l7icVmNf950GO/niUuUHU4nHI56+g
rqdn8gvYbgcNSD5izCH0L3hz1qAKy9Cr13dqsk7zYDOpyAM4dDYVjnIwT0hA97l5
p8ObwoHqqxLOszXHOvSiEeyHMMsMhskLhdaMNWQTnNyLuY0ouZ41X17AqMPIs/fV
gLdcM+7SOyrTwnD3bDA6OosXEF7/VaaRV1H/Wn8U1+gEsMoLXx5au+UESoy0JHMv
RwbMMGrgRkb4yq7WIdBxW2VpPtfQHencLROCKPuF1Xot/uRrwOxlT1jrUj4eMDyr
ZNbLRN9edAEKQP2F7j/NMFFNDHKvtgJQtiA9RiebUlIxfxCS+4/F1ASqGVCYGX4D
Q0cr80VoI4KxHZouT4X7RcoSEpQqLVnEuWghr8MENdZkjn7MVWc/sRr0zUxNhM/R
1bHy/AxXP1QcitteulVHjUDh9DfCS5gevaahR7O7cRsSRQV296ieG2grJrKQwzvQ
aKKRl6F91+XS4gbCyol/GTeu44saE/F1J1Z4V0pc8ZSezIe4ES1bWBoX2CdS6hW5
z7nVqYEpP/Q0jlYresnsS9M7LM7WHEFiVmTPD7/hJDp8b2aS+Ch9pOVFEmx7weLd
C1IUvalpDMIeRiC0TTw=
=Fqxm
-----END PGP SIGNATURE-----
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
If it's a translation it's not the same thing at all. A translation can
make it safe.

Yes, the _ function can check that the format specifiers of the
translated string match those of its argument, but that's not something
the compiler or printf knows about. To printf, it will be just as much a
user-specified string as argv[1].

Once you have sanitized the input, though, it in theory becomes trusted
(despite being user-supplied). I really think it is necessary to draw
that distinction.

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJrDU+AAoJEKmxP9YxEE4rr3QP/i/4rM2oIXYZ3f5WjzANWO9M
SHXB5udWnYAh+gJCfOuuCgRGU6Mluh3AZ1+C6kWAfH/gjjmTJnIVAZrPG7oVQgKn
4jGVUC5doDx++9mnLoqdvCPn6b9R/z2aLVa/SQSifo4SpdXjIDbHe7DFTlT0eBpp
a3rEUyta6kjHl5WtKFUP5hNg7HZnhpZlS8EOGqQH2J8b2D93mYVKdNDpXNMAaEuH
jOcx2z89hNiodcczZpyktPYwF372FxFvbg/jYn+XOQ1p6kbDlGP6n+B/POf0urt5
Xx6s5gks0iSFNywHWFuxxRE63SNGnzERYktdjOOMvDuY2z149bbOy4nub/oxnxAW
alZZOFetza+yG728KtMdVYWqe3OkhQO8Um8aKLFSX+/HH9w00aCBzQhbdWBDSoJW
lt6QnNbmSCkmAgneYGGKlqI8Muka0Ws3rRZZWFsAtngWNqJh+GBHpSBONHqft7EU
uWTMSglxNe2ysfrX48FDpFPXK4oVKeeuZNMKvoUDZAvx+dUEwAM4thAJ6lbs8yJM
v28OQvXqFHzPBp8VLg1T3MzljLOAPDhuUOF/CH0QonH9ehvreyjXYyHLKe7Fyw+s
k5mcWEbLBeyW/4xuzGMeSayw3rl3G1sdsHNaDxb0XpASU9aX4xNG84o3zc7XcDui
cRFYeZUz6O0nbebQiS7Z
=bfQR
-----END PGP SIGNATURE-----
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nate said:
After reading the links posted by the OP, I'll say in Microsoft's
defense that this is not a bug but a feature :) A somewhat common source
of security problems in C programs are so-called "format string
vulnerabilities"; if a user-supplied string is passed to a function like
printf(), the user might include %n specifiers, which would have the
effect of writing to some area of memory. In some cases this can be
exploited to get the program to do something that it is not supposed to,
perhaps letting the user do things that he ought not be allowed to do.

The proper fix, of course, is not to pass user-supplied strings to
printf(), at least not without sanitizing them first. However, since
there is a substantial amount of old (and, sadly, new) code written by
people who didn't realize the danger of such code, and relatively few
legitimate uses of %n, Microsoft made the decision to disable this
feature by default. Enabling requires calling a Microsoft-specific
function. This breaks ISO compliance, of course, and evidently confuses
some programmers, but does make the world a somewhat safer place, at
least in the short term.

The wisdom of this decision is certainly subject to debate, but it *was*
a decision, not an accident, and has at least some justification.

If they advertise ISO compliance, then their compiler is (obviously)
definitely broken. I think that might break POSIX too.

Calling MSVC++ C, on the other hand, is more than a little misleading.

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIcBAEBAgAGBQJJrDWlAAoJEKmxP9YxEE4rqzIQAJUTVMg5Q88IjjtqAuEhj9Sz
t9f43pU9cglC1Ap/ibOhWyWs5P0Xlpg49nYNvmDoc2EF7fin0w9MwerZ/b1Ythve
fxbgelyoMuhealjgI5jLGAMd/R/quUKpjmZtrMyM1Q/2D/+vaKWAybpxxGwjDBXt
Y19D4cACd5MrEA0oN8Y81Y1hoetiZlBjNxPo3FKAz1t4RvgSTgq1+sxnY4nKu9aq
SY+as0G2rX+Zvizp84LFZuMR/cchrJJcUIFiM5mxn8JvtvjCqEPF8gt/2LPL+0Ge
XSY8/wdjkR3qO+U7YJncIh8oY1xb43Q5CcurWb7U8L7LXZbf2xVWz5b38vfe1zpj
MCqjF+pAHnG9aEJsKQ/91qn/Zw6bkTwMq776Z/fZVmsX/L7ha1Cwv7+pc2iUdxtk
8TbCXB7PNG9DiBRSDIJUzSu8NNGwjx7BrH/CQ7nBEPM8oXEGdksfHhXIpOVakhmM
nsfxMvjwAdIe+Q6fM3HjF5kloGZQ51gYFL4Hqf+GN0CEQxt4M4q9Bb90E421NEBd
gJOOHzKp4je75ctNIUi+h7Lea+L/GzMP+UJWwkqacR7cWTv6aCt6hru1fgvCQUEs
mHOyHk9mETLMAzKWHtBoVJKWrHCVmCYxYIVGeIzCRib6ZaAIBAh+gY2dJH54cnxc
PPXBU1y2SrZAgn2JD/7h
=VRYj
-----END PGP SIGNATURE-----
 
P

Phil Carmody

Keith Thompson said:
Phil Carmody said:
%n is barely less secure than %s. OK, one could performs a write
to an arbitrary location, the other only performs a read from an
arbitrary location, but both are breaking out of the sandbox that
any sensible programmer would be working in.
[...]

How is %n less secure than %s?

Why do you think I raised the comparison?

Because, if not used correctly causes unwanted writes rather than
unwanted reads. Unwanted writes are considered more insecure than
unwanted reads, as unwanted writes can modify things, unwanted
reads can only leak information.
If used properly

Keep up. The presumption is that these strings are not being
used correctly.
, %n is perfectly
safe; just pass the address of a writable integer object. %s can't be
used safely unless you can control what will appear on stdin.

stdin doesn't have to enter into things at all.

Phil
 
K

Keith Thompson

Phil Carmody said:
Keith Thompson said:
Phil Carmody said:
This is from the VS2008 documentation on printf() format specifiers:

Security Note The %n format is inherently insecure and is disabled
by default; if %n is encountered in a format string, the invalid
parameter handler is invoked as described in Parameter Validation.
To enable %n support, see _set_printf_count_output.

%n is barely less secure than %s. OK, one could performs a write
to an arbitrary location, the other only performs a read from an
arbitrary location, but both are breaking out of the sandbox that
any sensible programmer would be working in.
[...]

How is %n less secure than %s?

Why do you think I raised the comparison?

Because, if not used correctly causes unwanted writes rather than
unwanted reads. Unwanted writes are considered more insecure than
unwanted reads, as unwanted writes can modify things, unwanted
reads can only leak information.
If used properly

Keep up. The presumption is that these strings are not being
used correctly.

Then all bets are off anyway -- but I suppose I can see your point
about one being less secure than the other.
stdin doesn't have to enter into things at all.

Right. We were discussing printf; I was thinking of scanf, for which
"%s" is unsafe. Sorry about the confusion. (Somebody pointed out my
mistake earlier; I neglected to acknowledge the correction.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top