Secure Programmer: Keep an Eye on Inputs
An anonymous reader writes "This article discusses various ways data gets into your program, emphasizing how to deal appropriately with them; you might not even know about them all! It first discusses how to design your program to limit the ways data can get into your program, and how your design influences what is an input. It then discusses various input channels and what to do about them, including environment variables, files, file descriptors, the command line, the graphical user interface (GUI), network data, and miscellaneous inputs."
The Perl language has built-in "taint-checking" enabled via the -T command line switch which causes Perl to automatically keep track of all information that possibly came from a user input and not allow any of it to do anything harmful (basically end up on a command line or in a file name).
There are other harmful things that data can wind up doing that Perl can't check for. Things like being used as SQL queries, or the classic "pass the price as a CGI parameter" mistake. Taint checking is more useful as a reminder that you need to validate input than a way of keeping potentially bad input isolated.
"They redundantly repeated themselves over and over again incessantly without end ad infinitum" -- ibid.
Perl programmers interested in writing secure scripts should *definitely* know about the -T (taint checking flag).
From the FAQ:
As we've seen, one of the most frequent security problems in CGI scripts is inadvertently passing unchecked user variables to the shell. Perl provides a "taint" checking mechanism that prevents you from doing this. Any variable that is set using data from outside the program (including data from the environment, from standard input, and from the command line) is considered tainted and cannot be used to affect anything else outside your program. The taint can spread. If you use a tainted variable to set the value of another variable, the second variable also becomes tainted. Tainted variables cannot be used in eval(), system(), exec() or piped open() calls. If you try to do so, Perl exits with a warning message. Perl will also exit if you attempt to call an external program without explicitly setting the PATH environment variable.
I'm a bloodsucking fiend! Look at my outfit!
Ya you can talk about inputs to programs and how misc. and unwanted data get in there but watch for buffer overruns because thats what can really kill your program.
There is or can be built a machine that can simulate any physical object. -Church-Turing principle
Java
.NET
XML
Maybe the testing methodology you cite isn't so useful then, if you have to change your code when you're done testing. Backdoors are only bad if you put them in in the first place. Test First Design might be a better approach than Code an insecure backdoor as a test.
meh.
See this paper. I remember reading the original document in (CACM IIRC) and was pleased to see it updated showing just how far "forward" we've come.
forms and web interfaces that you provide the user aren't the only way to interact with your application.
// do something very important.
So true, so true. For example (in PHP)
<?
if ($login='Admin' && $pass='19ak129')
$secure=true;
if ($secure)
{
}
?>
In many cases this script's security could be bypassed by adding "&secure=true" at the end of the URL!
I prefer to generate or define a set of values that are acceptable and check with in_array().
EG:
<?
$acceptable=array('a', 'b','na');
if (!in_array($acceptable, $_REQUEST[check]))
die ('Sorry. Input in field "check" is invalid');
?>
Or by using a regex. Assume that the input must be a number:
<?
$match="/[0-9]+/";
if (preg_replace($match, '', $_REQUEST[number]))
die ('You must put in a number');
if (strlen($_REQUEST[number]>5))
die ('Number you have entered is out of range');
?>
You can oftentimes functionalize these so that it's as simple as:
<?
if ($error=Valid_Integer($_REQUEST[number]))
die($error);
?>
Simple methods that can greatly enhance security!
I have no problem with your religion until you decide it's reason to deprive others of the truth.
Yeah, web applications were a mess, and bloody complex to do rather basic tasks. Fortunately, most platforms are getting better, and more conservative with age. For example, your PHP URL trick wouldn't work in a recent default installation of PHP where "register_globals" (the automagic system that makes all variables from HTTP POST, URL's, cookies, and sessions all the 'same') is "Off".
I guess the moral of the story is that the web is young, and web platforms are even younger. With any luck, many of these headaches will disappear with time.
BTW, anyone know of some magical code to block SQL injection vulnerabilities?
I wrote a similar article recently for SysAdmin magazine, although the focus is more about Perl.
Magical!? Yes. It's really easy in fact. Simply do NOT use direct user input within an SQL statement. That seems really restrictive but it's not - it simply requires that you push back CHOICES to the user in creating your form... all sara john ...then you use the values (validated to be only numbers) to back-fill your SQL statement.
If you are really feeling risky, then at the very least make sure that every character you recieve is [A-Za-z0-9 ], length verify it to make sure it matches the lenght of your field, and reject anything with single or double quotes embedded.
It's not magic, it's... programming.
Use placeholders. PEAR DB supports them, as do other database abstraction layers. As long as you _always_ use placeholders you will be safe against SQL injection.
If you can't depend on PEAR DB (or similar) to be installed / at the correct version, you could quickly build yourself a function that takes a variable number of arguments: a SQL statement containing '%s' (for strings) or %d (for numerics) followed by potentially hostile arguments. Run each of the arguments through mysql_escape_string (or equivalent for your DB) then build your SQL statement using sprintf. Note: I haven't tested that approach; use with caution.
That information can be contained inside a constant and compiled into the final executable.
Can, yes, can. But they wouldn't be very useful.
Not very useful? Here are examples which require no input and which I think are useful:
- a cpu meter (no input, just system calls).
- an aquarium simulation screen saver.
- one-off applications which produce a static output from hard-coded input.
- complex mathematical calculations
- true, false, bg, fg, ps, top, logout commands/utilities in Linux
- a clock display application
Not to ignore the rest of your comment, but wouldn't initially setting $secure to a null value solve that problem?
// do something very important.
<?
unset($secure);
if ($login='Admin' && $pass='19ak129')
$secure=true;
if ($secure)
{
}
?>
Need a Linux consultant in New Orleans?
Any process can send any message to any other process. Talk about insecure.
Accourding to http://security.tombom.co.uk/shatter.html it is much worse than just that. Not only can anyone send such a message, but the messages can even force the receiver to execute arbitrary code.
Do you care about the security of your wireless mouse?