Be a Supporter!

Php: Good Habits/security Concerns

  • 1,761 Views
  • 11 Replies
New Topic Respond to this Topic
Sir-Davey
Sir-Davey
  • Member since: Jul. 9, 2001
  • Offline.
Forum Stats
Member
Level 19
Blank Slate
Php: Good Habits/security Concerns Jan. 8th, 2006 @ 03:39 PM Reply

PHP: Main

So, you know PHP pretty well, and you think you can start making awesome forum software, or better yet, your own portal? That's great! Except there's one problem: if you're just starting out, the chances are really high that your code is vulnerable to injections, or that you're just not making very good code. Don't worry though, this is a phase almost all PHP programmers go through. I will show you how to make your scripts a bit more secure/more compatible than before.

==Part I: register_globals==
If you've ever worked with forms, or dynamic id retrieval before, than you might be used to getting the parameter sent by simply calling a variable named like the parameter. If that wasn't too clear, here's an example of a URL that you would like to get the ID from
http://www.somesite...wesome_page.php?id=2

You're probably thinking "oh, that's easy as pie! I just need to use the $id variable!". Well, if you think that, you are BAD CODER (don't worry, it'll get better when you finish reading this long tutorial). You should use $_GET['id'] . Am I not making much sense to you? Good. Here's how all this stuff actually works:

When you go to a page like hello.php?firstname=john&lastname=doe , your browser sends what are called GET variables to your script. GET variables are variables that show up solely in the URL. This is generally used so people can directly access some content just by typing the URL. This should usually be short, because nobody likes really long urls anyways (and there is a physical limit).

Now, usually when you submit a longer form such as the post I am writing right now, your browser sends all the data as POST variables. These variables don't show up in the URL, and are usually handled "in the background" by your browser (I won't go in depth on how they really are sent). POST data does not have any physically reachable limit, so you can send pretty much all the data you want with a POST.

Now, to make it much easier for beginners, the people developing PHP thought it would be a good idea to have PHP automatically handle this data and flawlessly give you nice variables you can immediately work with. This setting is called register_globals, and it is sadly automatically enabled by default on most servers you will find.

But as I said, the variables you can use with this setting enabled are not really good. Imagine if you have a script that does not do an initial setup for a variable called $cheese, and you just take it for granted that $cheese will be empty. Well, if I do yourpage.php?cheese=MALICIOUSDATA, $cheese will contain MALICIOUSDATA and you won't even know what happened! Thankfully, to avoid these types of problems, there is a much safer and sure way to access data sent to the script! They're arrays, and they're called super globals. That is, you can access them at any time in the script, in any function and any class, without worrying about variable scope. Pre-defined superglobals are usually in ALL CAPS, and prefixed with an underscore ( _ ). Simple enough.

So, now that you know the difference between GET and POST variables, you can simply access the array $_GET['name'] and $_POST['name'] ! This will make sure that none of your regular variables are overwritten. So, an example to access some GET data would be:
http://www.yoursite...ob&lastname=Dole
echo $_GET['firstname'] . ' ' . $_GET['lastname'];
would output
Bob Dole

Same would go for $_POST. You need to make sure the element you access is between quotes (single quotes are better. This is covered in the next chapter).

There are a few predefined variables:
$_GET['name'] : Accesses the value stored in the GET variable 'name'. Ex: $_GET['id'] gets the value '2' from test.php?id=2
$_POST['name'] : Accesses the value stored in the POST variable 'name'. Ex: $_POST['postBody'] gets the value of the form element named 'postBody'
$_COOKIE['name'] : Accesses the value stored in a user cookie 'name'. Ex: $_COOKIE['userId'] gets the value of 'userId' that was in the viewer's cookie.
$_REQUEST['name'] : Regroups $_GET, $_POST and $_COOKIE. Please, don't use it at all unless you're sure you want to accept variables from any of the three.
$_FILES['name']['property'] : Accesses the property 'property' of the file 'name'. Ex: $_FILE['flash']['size'] gets the size (in bytes) of the file in the form labeled as 'flash'
$_SERVER['NAME'] : Accesses the server variable 'NAME'. Ex: $_SERVER['REMOTE_ADDR'] gets the IP address of the person viewing the page.

==Part II: Strings==
You know how when you want to echo a variable, you do
$bob = 'My name is Bob';
echo "The variable Bob contains this: $bob";

Well, it's again a pretty bad habit. Let me explain:

When you use double quotes ( "lol" ), PHP searches the entire string for an eventual variable, or character that could be in the string. Single quotes do not do ANY replacement, so 'Hello, $bob' will be Hello, $bob . $bob will not be outputted, and the $ will be kept. This is called a literal string. This is why when you want to output a simple variable with some text, you should use the dot ( . ) operator, which appends a string to another. So, taking our example above, you should do
echo 'The variable Bob contains this: ' . $bob;
PHP won't ask itself any questions, and will simply output 'The variable Bob contains this: ', and then will output the $bob variable. Not only is this slightly faster to parse, but it also makes your code look cleaner, and will allow syntax highlighters and code-completion to work fine.

Now, I understand that if you have a giant string full of variables, you should use double quotes and just type it all. This is perfectly normal, and saves some useless typing.

Note: If you want to output a newline and you're using single quotes, do not just put \n in single quotes, it will be displayed as \n! You should close the string, and append a \n in double quotes (ie: echo 'Hello, ' . "\n" . 'world!')


BBS Signature
Sir-Davey
Sir-Davey
  • Member since: Jul. 9, 2001
  • Offline.
Forum Stats
Member
Level 19
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 8th, 2006 @ 03:40 PM Reply

==Part III: Variable Escaping For SQL Queries==
When you're using user input to put in a query, like a name, you always need to escape special characters. This is probably nothing new to you, so I'll just explain to you how you REALLY should make sure that the stuff you're sending to MySQL is safe.

By default, PHP also has the 'awesome' feature of using addslashes on all input variables (GET, POST and COOKIE). This is to prevent beginners from making injectable code. But this is both not a good thing for advanced people, but also not safe enough.

The best way to make sure that TEXT is going to be properly escaped for MySQL is to use the function mysql_real_escape_string($variable). This will escape all the potentially dangerous characters in a query. These values are \x00, \n, \r, \, ', " and \x1a . But if you want to use this function, you must first have a connection to a database, so I made my own which doesn't require any database connection:

function EscapeStr( $str )
{
// \x00, \n, \r, \, ', " and \x1a.
//because mysql_real_escape_string requires a connection
$bad = Array("\\", "'", '"', "\n", "\r", "\x00", "\x1a");
$good = Array("\\\\", "\'", '\"', "\\n", "\\r", "\\x00", "\\x1a");
return str_replace($bad, $good, $str);
}

To use it, just do
$safe = EscapeStr($_POST['safe']);
And everything should be fine. But BE WARNED. THIS IS NOT FOR NUMERIC VALUES!!!!

If you're using a MySql query like
$sql = 'SELECT * FROM posts WHERE id=' . EscapeStr($_GET['id']);
Escaping slashes will not protect you completely. To be 100% sure id's are good, use the intval($var) function. This is turn any string into 0 and '34' to 34. The code above becomes:
$sql = 'SELECT * FROM posts WHERE id=' . intval($_GET['id']);

==Part IV: Setting Coding Standards==
Chances are you are starting a big project, and you're going to have a lot of code to write. Before you start coding a lot, you should set yourself some standards as to how you're going to type the code.

I, for one, put new lines after if statements, and brackets. I also space parenthesis around if statements. An example explains it a bit better:

if ( something )
{
//something
}

This only makes your code more readable (in my opinion, of course), and nothing else. Although it's a good habit to decide exactly how you're going to write everything.

You should also use a sure naming scheme. I use lowerCamelCase for variables, and UpperCamelCase for everything else (functions, classes, array indexes, etc). You should also decide of a sure order for arguments in a function. I always put the least significant property variable' at the end. Imagine a function that shortens a string and adds something at the end. I would use the following order:
function ShortenString ( $variableToShorten, $lengthToTrime, $stringToAddAtTheEnd )
Defining a global way of ordering your variables will help you in the future when you're not exactly sure how an old function you made wants its parameters. You won't have to look at the definition anymore, because you'll know the least significant parameter is at the end.

This concludes this tutorial. I hope you enjoyed reading it as much as I enjoyed making it. I promise that my next tutorial will be more advanced, and be useful for advanced programmers. It's going to be about modularity and abstraction layers. It will be cool, I just need another lazy Sunday.


BBS Signature
DFox
DFox
  • Member since: Aug. 9, 2003
  • Offline.
Forum Stats
Member
Level 30
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 8th, 2006 @ 04:35 PM Reply

Very cool tutorial.

Are you going to post it in PHP: Main or would you like me to just add it to the list?


BBS Signature
Zendra
Zendra
  • Member since: Sep. 7, 2003
  • Offline.
Forum Stats
Moderator
Level 51
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 9th, 2006 @ 03:13 AM Reply

Very nice detailed and your tutorial has a good structure. I asume this tutorial is based on what I said in this topic and I think it's good you're giving attention to it. :)
Nice job.

henke37
henke37
  • Member since: Sep. 10, 2004
  • Offline.
Forum Stats
Member
Level 30
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 9th, 2006 @ 04:33 AM Reply

You didn't have to write that escape function, not only has php the mysql_real_escape_string function, but also the mysql_escape_string function.


Each time someone abuses hittest, God kills a kitten. Please, learn real collision testing.

blackbomb
blackbomb
  • Member since: Dec. 27, 2006
  • Offline.
Forum Stats
Member
Level 04
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 5th, 2007 @ 02:47 PM Reply

i think you forget to tell how to corrige the include exploit its really important lot of pepoele got hacked with this exploit.

eWhabs
eWhabs
  • Member since: May. 4, 2006
  • Offline.
Forum Stats
Member
Level 13
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 5th, 2007 @ 03:02 PM Reply

At 1/9/06 04:33 AM, henke37 wrote: At 1/5/07 02:47 PM, blackbomb wrote:

This thread is one year old...


-Disregard females (fuck bitches)
-Acquire currency (get money)
-Ignite cannabis frequently (smoke sum with your homies)

BBS Signature
blackbomb
blackbomb
  • Member since: Dec. 27, 2006
  • Offline.
Forum Stats
Member
Level 04
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 5th, 2007 @ 03:41 PM Reply

dosent mean we cant read it and comment it the include exploit was created before this tread was created

WoogieNoogie
WoogieNoogie
  • Member since: Jun. 26, 2005
  • Offline.
Forum Stats
Supporter
Level 15
Programmer
Response to Php: Good Habits/security Concerns Jan. 5th, 2007 @ 03:48 PM Reply

At 1/5/07 03:41 PM, blackbomb wrote: dosent mean we cant read it and comment it the include exploit was created before this tread was created

Absolutely. I agree, and think you're in the clear.

blackbomb
blackbomb
  • Member since: Dec. 27, 2006
  • Offline.
Forum Stats
Member
Level 04
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 5th, 2007 @ 04:01 PM Reply

thanks for your support the only thing i dislike on this forum is that theres no way to edit our post like in certain forum so even if i contact the author he wont be able to corect

eWhabs
eWhabs
  • Member since: May. 4, 2006
  • Offline.
Forum Stats
Member
Level 13
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 5th, 2007 @ 04:15 PM Reply

At 1/5/07 03:41 PM, blackbomb wrote: dosent mean we cant read it and comment it the include exploit was created before this tread was created

Yeah, I apologize, what I said was useless...

do you pardon me ?

-Disregard females (fuck bitches)
-Acquire currency (get money)
-Ignite cannabis frequently (smoke sum with your homies)

BBS Signature
Craige
Craige
  • Member since: Jul. 17, 2004
  • Offline.
Forum Stats
Member
Level 08
Blank Slate
Response to Php: Good Habits/security Concerns Jan. 5th, 2007 @ 04:49 PM Reply

I don't know why I didn't comment on this a year ago, but I will now, as I feel it is necessary.

Firstly, I did not like your comments about register globals. I would like to point out they are NOT evil IF you practice good coding. Although PHP does not enforce it, you should always pre-define your variables before using them. If you do this, register_globals will pose almost no threat to the security of you script. That being said, I'm going to turn around and say you still, however, should not be using them. They are being phased out in PHP 5, and will no longer be available in PHP 6. They were not evil, but they were not a good idea either.

Secondly, your comment about strings. Single quotes and double quotes have only a minuscule difference in time, and that's when you're using them as one whole string. When you combine strings with the full stop operator (.), it slows down execution, why? Lets take a look.

Say you have the following string:

print 'Foo' . $somevar . ' bar ' . $anothervar;

What does PHP have to do to output this string? It's a lot more then meets the eye. PHP as to:

1) Create a new, temporary string
2) Put "Foo" in there
3) Put the value of $somevar in there
4) Create a new, temporary string
5) Put the first temporary string in there
6) Put " bar " in there
7) Create a new, temporary string
8) Put the second temporary string in there
9) Put the value of $anothervar in there
10) Send the final temporary string to print, for screen printing

A lot more work then just finding and replacing variables.

Example taken from http://hudzilla.org/phpwiki/index.php?title=R ead_the_manual_carefully