21.03.2013 Views

Problem - Kevin Tafuro

Problem - Kevin Tafuro

Problem - Kevin Tafuro

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

components of the system are trusted, even after you have authenticated the user<br />

on the other end!<br />

Prefer rejecting data to filtering data.<br />

If you determine that a piece of data might possibly be malicious, your best bet<br />

from a security perspective is to assume that using the data will screw you up<br />

royally no matter what you do, and act accordingly. In some environments, you<br />

might need to be able to handle arbitrary data, in which case you will need to<br />

treat all input in a way that ensures everything is benign. Avoid the latter situation<br />

if possible, because it is a lot harder to get right.<br />

Perform data validation both at input points and at the component level.<br />

One of the most important principles in computer security, defense in depth,<br />

states that you should provide multiple defenses against a problem if a single<br />

defense may fail. This is important in input validation. You can check the validity<br />

of data as it comes in from the network, and you can check it right before you<br />

use the data in a manner that might possibly have security implications. However,<br />

each one of these techniques alone is somewhat error-prone.<br />

When you’re checking input at the points where data arrives, be aware that components<br />

might get ripped out and matched with code that does not do the<br />

proper checking, making the components less robust than they should be. More<br />

importantly, it is often very difficult to understand enough about the context of<br />

the data well enough to make validation easy when data is fresh from the network.<br />

That is, routines that read from a socket usually do not understand anything<br />

about the state the application is in. Without such knowledge, input<br />

routines can do only rudimentary filtering.<br />

On the other hand, when you’re checking input at the point before you use it,<br />

it’s often easy to forget to perform the check. Most of the time, you will want to<br />

make life easier by producing your own wrapper API to do the filtering, but<br />

sometimes you might forget to call it or end up calling it improperly. For example,<br />

many people try to use strncpy( ) to help prevent buffer overflows, but it is<br />

easy to use this function in the wrong way, as we discuss in Recipe 3.3.<br />

Do not accept commands from the user unless you parse them yourself.<br />

Many data input problems involve the program’s passing off data that came<br />

from an untrusted source to some other entity that actually parses and acts on<br />

the data. If the component doing the parsing has to trust its caller, bad things<br />

can happen if your software does not do the proper checking. The best known<br />

example of this is the Unix command shell. Sometimes, programs will accomplish<br />

tasks by using functions such as system( ) or popen( ) that invoke a shell<br />

(which is often a bad idea by itself; see Recipe 1.7). (We’ll look at the shell input<br />

problem later in this chapter.) Another popular example is the database query<br />

using the SQLlanguage. (We’ll discuss input validation problems with SQLin<br />

Recipe 3.11.)<br />

Understanding Basic Data Validation Techniques | 73<br />

This is the Title of the Book, eMatter Edition<br />

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!