
09-29-2008, 08:31 PM
|
|
Disabled
|
|
Join Date: Sep 2008
Location: England
Posts: 19
|
|
PHP: Secure ways to write code?
Hi,
Bare with me as I'm a novice and very new to PHP.
I've been wondering about securing my PHP code in my pages.
I was thinking of setting my MySQL database connections into functions in a separate file that will be included to the page via require_once.
- Is that a means of securing code at all?
Are there any other precautions I can take in order to secure my code?
I was also thinking of instead of writing variable names like $variable but to 'anagram' them like $riavabel or something.
I'm probably going over the top but considering I keep hearing about some smart-alek doing this that and the other to this person's site and that person's site I just want to make sure I'm being secure as much as I can.
I want to learn to be secure with my PHP code so I can practise it from the start - rather than having to adapt to new ways of writing code later.
Any help, tips, suggestions all appreciated. But please spare criticism I'm trying to learn this all on my own!
|

09-29-2008, 09:05 PM
|
|
Web Hosting Master
|
|
Join Date: Aug 2003
Location: California, USA
Posts: 579
|
|
For your database abstraction, you might want to look into creating a class, for instance:
PHP Code:
<?php class MySQL // extends Database { var $conn; var $resource;
function MySQL($host, $user, $pass) { mysql_connect($host, $user, $pass); } function query($sql) { $this->resource = mysql_query($sql); return $this->resource; } function get_array() { return mysql_fetch_assoc($this->resource); }
// make sure to always sanitize input before throwing it into your database // queries by using the database type's escape string. function escape($str) { return mysql_real_escape_string($str); } // etc
}
$conn = new MySQL('localhost', 'user', 'pass'); $sql = "SELECT * FROM table WHERE field ='" . $conn->escape($_POST['field']) . "' LIMIT 1"; $conn->query($sql); $results = $conn->get_array();
foreach ($results as $result) { echo $result['field']; }
?>
I don't want to write the whole thing for you, but that should give you an idea on where to jump off at.
As for changing variables to anagrams, it will have no effect on a user hacking your code. The only thing that can semi-relate is if you have register_globals on. You might find this snippet of code handy to throw in any script you use, in a common global include file:
PHP Code:
<?php // taken from php.net function unregister_globals() { if (!ini_get('register_globals')) { return false; }
foreach (func_get_args() as $name) { foreach ($GLOBALS[$name] as $key=>$value) { if (isset($GLOBALS[$key])) unset($GLOBALS[$key]); } } }
unregister_globals('_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
?>
And finally, the last major thing you need to look out for is XSS, or cross-site scripting. This can be easily eliminated by the following function:
PHP Code:
<?php function xss_clean($str, $charset = 'ISO-8859-1') {
$str = preg_replace('/\0+/', '', $str); $str = preg_replace('/(\\\\0)+/', '', $str); $str = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u',"\\1;",$str); $str = preg_replace('#(&\#x*)([0-9A-F]+);*#iu',"\\1\\2;",$str); $str = preg_replace("/%u0([a-z0-9]{3})/i", "&#x\\1;", $str); $str = preg_replace("/%([a-z0-9]{2})/i", "&#x\\1;", $str); if (preg_match_all("/<(.+?)>/si", $str, $matches)) { for ($i = 0; $i < count($matches['0']); $i++) { $str = str_replace($matches['1'][$i], new_html_entity_decode($matches['1'][$i], $charset), $str); } } $str = preg_replace("#\t+#", " ", $str); $str = str_replace(array('<?php', '<?PHP', '<?', '?>'), array('<?php', '<?PHP', '<?', '?>'), $str); $words = array('javascript', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window'); foreach ($words as $word) { $temp = ''; for ($i = 0; $i < strlen($word); $i++) { $temp .= substr($word, $i, 1)."\s*"; } $temp = substr($temp, 0, -3); $str = preg_replace('#'.$temp.'#s', $word, $str); $str = preg_replace('#'.ucfirst($temp).'#s', ucfirst($word), $str); } $str = preg_replace("#<a.+?href=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>.*?</a>#si", "", $str); $str = preg_replace("#<img.+?src=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>#si", "", $str); $str = preg_replace("#<(script|xss).*?\>#si", "", $str); $str = preg_replace('#(<[^>]+.*?)(onblur|onchange|onclick|onfocus|onload|onmouseover|onmouseup|onmousedown|onselect|onsubmit|onunload|onkeypress|onkeydown|onkeyup|onresize)[^>]*>#iU',"\\1>",$str); $str = preg_replace('#<(/*\s*)(alert|applet|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|layer|link|meta|object|plaintext|style|script|textarea|title|xml|xss)([^>]*)>#is', "<\\1\\2\\3>", $str); $str = preg_replace('#(alert|cmd|passthru|eval|exec|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2(\\3)", $str);
$bad = array( 'document.cookie' => '', 'document.write' => '', 'window.location' => '', "javascript\s*:" => '', "Redirect\s+302" => '', '<!--' => '<!--', '-->' => '-->' );
foreach ($bad as $key => $val) { $str = preg_replace("#".$key."#i", $val, $str); } return $str; } function new_html_entity_decode($str, $charset='ISO-8859-1') { if (stristr($str, '&') === FALSE) return $str;
if (function_exists('html_entity_decode') && (strtolower($charset) != 'utf-8' OR version_compare(phpversion(), '5.0.0', '>='))) { $str = html_entity_decode($str, ENT_COMPAT, $charset); $str = preg_replace('~&#x([0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str); return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str); } $str = preg_replace('~&#x([0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $str); $str = preg_replace('~&#([0-9]{2,4});{0,1}~e', 'chr(\\1)', $str);
if (stristr($str, '&') === FALSE) { $str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES))); } return $str; } ?>
PHP Code:
<?php // USAGE:
$field = xss_clean($_POST['field']);
?>
Sorry if this is a little overwhelming. If you need anything explained in further detail I'll be glad to help.
|

09-29-2008, 09:12 PM
|
|
Community Guide
|
|
Join Date: Jan 2006
Location: Athens, Greece
Posts: 1,479
|
|
The top issue of new php users is not sanitizing form input.
Google "sql injection" to get an idea.
Simpy put: If you have a html form and one of the fields is a date then
on the code you should also check that the text provided is a date and not
some malicious content.
For example, another common mistake is with numbers
User requests this page:
And you do a search in the database:
Code:
"SELECT * FROM products WHERE id = ".$_GET['id'];
Now if a user would not enter a number in the URL, he would be able to
delete or your tables by injecting your query with additional sql commands.
So the proper way to avoid this would be;
PHP Code:
$id = 0; if (isset($_GET['id'])) $id = (int) $_GET['id']; $query = "SELECT * FROM products WHERE id = ".$id;
|

09-29-2008, 09:14 PM
|
|
Disabled
|
|
Join Date: Sep 2008
Location: England
Posts: 19
|
|
OK.
That was quite overwhelming yes but I do see where you are coming from. I'll have a go with these and if I find myself bewildered I'll give you a shout
Much appreciated all the same 
|

09-29-2008, 09:22 PM
|
|
Disabled
|
|
Join Date: Sep 2008
Location: England
Posts: 19
|
|
Thanks for that.
I can most certainly see the point in doing so.
In fact, the code makes more sense to code it like that to me, I wouldn't be able to see the point in keep id open on a aquery like the one you provided as an example.
Very many thanks 
|

09-29-2008, 09:29 PM
|
|
Aspiring Evangelist
|
|
Join Date: Jan 2005
Location: North-East, Indiana
Posts: 417
|
|
Yeah, while you asked a question that seemed small, it will return a lot of valid 'need to know' information. As you are dealing with a database, that means its a 'box full of valuables,' and you don't want people removing or viewing any more than you specify!
SQL Injections are very common (to amateurs,) and will undoubtedly upset you once it happens. The best thing that you can do is go to gods gift to geeks, http://google.com/, and type in 'How to protect against SQL Injections in PHP' and you will pull up VAST information on it! Remember to read all different articles as there will be many different ways to protect yourself.
The EASIEST way, as stated earlier I believe, to get hi-jacked with an SQL Injection is to pull up information out of your database via $_GET! Just remember to require the ID in Zero, add the number of the $_GET and pull up your info that way! Easy and Safe!
__________________
• PHP5 / MySQL / CUSTOM TEMPLATING / CLEAN & MAINTAINABLE CODING
• WEB DEVELOPMENT via CUSTOM DESIGN / PROGRAMMING
|

09-30-2008, 12:51 AM
|
|
Web Hosting Master
|
|
Join Date: Sep 2005
Location: India
Posts: 736
|
|
Some things to keep in mind:
1. Don't use register_globals. This is going to be removed in PHP6 anyway.
2. Don't use $_REQUEST unless necessary. Use $_POST, $_GET instead. This won't make your code secure but will make it easier to maintain and understand.
3. Input validation. Make sure that incoming data type is what you suppose it to be. Some functions you can use for input validation: isset, empty, filter_input, filter_var, ctype_alnum, ctype_alpha, is_numeric etc.
4. Whenever you insert/update data to a database, make sure to run it through mysql_real_escape_string
5. In development environment, set error_reporting to E_ALL and display_errors to On. In production environment set display_errors to Off
6. Don't store sensitive information in cookies.
7. Don't store sensitive information in session. Although session is more secure than cookies, the data is still visible to anyone who has access to the server. Use database based session handler for improved security.
Alternatively, pick a good framework. Most frameworks have all the above security measures built in. For example, the xss_clean() function posted by etogre comes from CodeIgniter framework.
Some recommended frameworks:
1. Zend
2. CakePHP
3. CodeIgniter - This is the easiest one to start of with.
|

09-30-2008, 07:52 AM
|
|
Disabled
|
|
Join Date: Sep 2008
Location: England
Posts: 19
|
|
Jatinder,
Thanks for the heads up on the frameworks.
I was thinking of getting Zend but considering you mentioned 2 others, I'll lookinto those first.
Thanks again 
|

09-30-2008, 07:58 AM
|
|
Web Hosting Master
|
|
Join Date: Sep 2005
Location: India
Posts: 736
|
|
Quote:
|
I was thinking of getting Zend but considering you mentioned 2 others, I'll lookinto those first.
|
I don't want to mislead you on this. Zend is an excellent framework and would be the optimal choice for bigger projects. But CodeIgniter is easier to start with especially if you are new to MVC frameworks.
So if you are comfortable with Zend, stick to it. Move to CodeIgniter only if you find Zend too complex.
Zend - Good choice for larger and complex projects
CodeIgniter - Good choice for smaller projects and very easy to learn for newcomers
|

09-30-2008, 08:08 AM
|
|
Disabled
|
|
Join Date: Sep 2008
Location: England
Posts: 19
|
|
Just as I expected.
I'll look right into it thanks
And like I said before, I just want to get all the hints and pointers I can get to ensure I'm writing secure code from the beginnning, I feel this will make it easier for me to adapt to new ways in the future and also, hopefully become a more valuable asset to people whether they are my employer or client
As my profile says, I'm more than efficient with HTML, XHTML and CSS and I've been doing them for about 5-6 years. I just want to actually get serious now since there is very little work for just HTML, XHTML & CSS develoeprs.
Also I've never found the PHP.net official manual easy to read - I've been doing this all by video tutorials and books, however the video tutorials are not super, but they are great to get the concept.
Again, thanks to all who have already shared their knowledge.
|

09-30-2008, 09:43 AM
|
|
Newbie
|
|
Join Date: Sep 2008
Location: Haarlem
Posts: 10
|
|
Like it has been said before, input validation is very important.
An easy way to validate inputs is to create a function to which you send the string and what you expect.
|

09-30-2008, 10:10 AM
|
|
Disabled
|
|
Join Date: Sep 2008
Location: England
Posts: 19
|
|
Quote:
Originally Posted by softwaredev
Like it has been said before, input validation is very important.
An easy way to validate inputs is to create a function to which you send the string and what you expect.
|
Like the example above?
Or do you have another example you could share?
Thanks 
|

09-30-2008, 10:36 AM
|
|
Newbie
|
|
Join Date: Sep 2008
Location: Haarlem
Posts: 10
|
|
Quote:
Originally Posted by CraigML
Like the example above?
Or do you have another example you could share?
Thanks 
|
I'm currently making a function that I'm going to use for my own projects.
As soon i have a decent code I'll post it here :-)
|

09-30-2008, 10:48 AM
|
|
Disabled
|
|
Join Date: Sep 2008
Location: England
Posts: 19
|
|
Quote:
Originally Posted by softwaredev
I'm currently making a function that I'm going to use for my own projects.
As soon i have a decent code I'll post it here :-)
|
Cool, that'll be much appreciated - like I keep saying to everything at the moment! 
|

09-30-2008, 11:18 AM
|
|
Aspiring Evangelist
|
|
Join Date: Jan 2005
Location: North-East, Indiana
Posts: 417
|
|
However, you don't want to use too much code… keep it simple and safe!
Some say, "You can never be too safe," but you really can. As long as you take the necessary steps to be safe, and not the unnecessary overloaded codes, then your code will run faster while maintaining stability and security.
__________________
• PHP5 / MySQL / CUSTOM TEMPLATING / CLEAN & MAINTAINABLE CODING
• WEB DEVELOPMENT via CUSTOM DESIGN / PROGRAMMING
|
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Linear Mode
|
| Postbit Selector |
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|
|
| Login: |
|
|
| Advertisement: |
|
|
| Web Hosting News: |
|
|
|