-
Problems
This line enable URL Rewriting . It must be enabled via the RewriteEngine directive! and if your .htaccess file is going to use rewrite rules, you should always include this line. Otherwise, you can’t be sure if its enabled or not. The string “on” is case insensitive.
You can do a few basic things to greatly reduce the risk of your site being cracked. Remember that security is all about raising the difficulty level for crackers—it’s one thing to be cracked by a professional crime ring, and another to have all your user’s passwords stolen by a 15- year old kid who can’t even program.
Every Web site should be taking these very basic steps to safeguard its users’ personal data:
Turn off register_globals
Too many PHP developers still write code such as this:
<?php
if (check_admin_priv()) {
$admin = 1;
}
if ($admin == 1) {
// Allow the user to see some privileged data
}
?>
This works fine for what you want it to do, which is set the $admin variable to 1 for legitimate administrators. But you also need to think about what your scripts can do that you don’t want them to do. This particular usage also lets any user who cares to use a URL like badcode.php ?admin=1 get administrator privileges if you have register_globals turned on. At the very least, you should be setting $admin to some other value if check_admin_priv() does not return true—but a better solution is to learn to live without register_globals.if (check_admin_priv()) {
$admin = 1;
}
if ($admin == 1) {
// Allow the user to see some privileged data
}
?>
PHP’s register_globals feature, which makes all GET, POST, COOKIE, SESSION, ENV, and SERVER variables immediately available via their plain variable names, is very popular because it seems to make development so much easier. Crackers can exploit this feature, however, to spoof cookies, run external JavaScript functions, load unsafe data into a database, and many other security nightmares. In large and complicated sites, register_globals can also lead to strange bugs as variables overwrite each other—especially if your team has members who do not choose good variable names (and most teams do). Only you can prevent your global namespace from becoming polluted with unsafe or unnecessary values.
The truth is that register_globals merely saves you a few keystrokes in development, at the price of massive risk, and the PHP community is slowly moving toward deprecating this feature for good. Instead, the PHP team has implemented superglobal arrays, which force you to ask for COOKIE values in cookies, POST values from posts, and so on—the gain for you is true global scope.You have time now to begin moving away from register_globals. Remember that you can easily write a shell, Perl, or PHP script to replace many of the global variables in your codebase— so this change doesn’t necessarily entail enormous amounts of hand labor. Use of superglobal arrays also encourages good programming practice—because good code asks for data and evaluates conditions as specifically as possible.
Users of PHP version 4.2.0 and higher, including PHP5, will notice that the register_
globals flag is now turned off by default. Take it as a sign of the times.
globals flag is now turned off by default. Take it as a sign of the times.
Check for string length and safety
Many PHP user registration programs contain lines like this:
if ($username && $password && $email) {
// Allow them to register
}
// Allow them to register
}
However, you should never assume that just because you’ve provided some nice form fields named Username and Password, people are using those fields to enter usernames and passwords. The pseudocode above just asks for the existence of a variable value without specifying anything about that value. You can and should be specifying precisely which types of data you accept into your database—the more precisely, the better. There is no good reason, for example, that anyone should ever be choosing a username or password that is longer than, say, 25 characters. If someone wants to use a 100-character string as a username, that’s a presumptive test that he or she may intend to do harm to your system. Why not just filter these people out before something bad happens, by testing for string length? It takes hardly any more development or runtime resources. This code snippet, for instance, will allow users to register only if all the variables contain fewer than 25 characters:
if (strlen($username) <= 25 && strlen($password) <= 25 &&
strlen($email) <= 25) {
// Allow them to register
}
Also, think about the type and content of these variables. If you have a form field for a user’s age, there’s no legitimate reason why anyone should be trying to stuff an array into it. You can use PHP functions like is_int, is_string, and is_bool to make sure your variable type is what it should be. Be particularly careful of any string that has tags (especially HREF and SCRIPT tags), singlequotes, double-quotes, or semicolons in it. You should either reject these outright if there’s no legitimate use for such characters—no username should have any of these characters in them, for example—or use escaping and encoding to turn them into strings that cannot evaluate in PHP or a browser.strlen($email) <= 25) {
// Allow them to register
}
You’re much safer, of course, if your database design fully supports the strategic goals of your code. So don’t use expansive types such as text or varchar to represent a Boolean, integer, or date type—make sure that the data type of each field is carefully matched to the actual data you intend to store in that field. Not only is your performance faster, but in the event someone manages to sneak unsafe code into your database, a restrictive type has a much better chance of choking on or truncating the bad data.
One-way encrypt passwords
A surprising number of “professional” Web sites store their users’ passwords in plain text in their databases. In doing so they are running the risk that one break-in can result in the compromise of the entire user data system—which often means that financial or other systems can no longer be trusted. Password theft is also becoming a source of legal liability for companies who fail to prevent or try to cover up the theft of their users’ personal data. The most frequently heard excuses for this practice are that the site needs to e-mail passwords to users who have forgotten them, and that the site’s employees need the capability to log in as a particular user to verify bugs reported by that user. Neither of these excuses washes. You have many other ways to deal with forgotten passwords and logging in as a particular user, some of which we will discuss in the “User Tools” and “Administrator Tools” sections that follow.The easiest way to get out from under the technical and legal risks of password theft is to make it impossible for even you to know what your users’ passwords are. The easiest way to accomplish this is to one-way encrypt user passwords on registration. You can do this either in PHP or in the database itself. The MySQL way to store passwords, for example, is by wrapping them in a built-in encrypting function called password():INSERT INTO user_table (username, password) VALUES(‘$username’, password(‘$password’)); Now when a user tries to log in, you query for the password using the same function: SELECT username, password FROM user_table WHERE username = ‘$username’ AND password = password(‘$password’); If you want to do the encryption on the PHP side, which has advantages, there’s a code sample with explanations in the “Login” section. Both methods use good one-way algorithms that, for most practical purposes, cannot be reversed as they require serious supercomputer time to decrypt. Whichever method you choose, the important point is to always encrypt your passwords before storing them.


No comments:
Post a Comment