Comments
bruce.armstrong wrote: Somebody just said it better than I did, and with more chops to say it: Open Letter to Mark Zuckerberg, Sheryl Sandberg & Facebook Mobile
Cloud Expo on Google News


2008 West
DIAMOND SPONSOR:
Data Direct
SOA, WOA and Cloud Computing: The New Frontier for Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
GOLD SPONSORS:
Appsense
User Environment Management – The Third Layer of the Desktop
Cordys
Cloud Computing for Business Agility
EMC
CMIS: A Multi-Vendor Proposal for a Service-Based Content Management Interoperability Standard
Freedom OSS
Practical SOA” Max Yankelevich
Intel
Architecting an Enterprise Service Router (ESR) – A Cost-Effective Way to Scale SOA Across the Enterprise
Sensedia
Return on Assests: Bringing Visibility to your SOA Strategy
Symantec
Managing Hybrid Endpoint Environments
VMWare
Game-Changing Technology for Enterprise Clouds and Applications
Click For 2008 West
Event Webcasts

2008 West
PLATINUM SPONSORS:
Appcelerator
Get ‘Rich’ Quick: Rapid Prototyping for RIA with ZERO Server Code
Keynote Systems
Designing for and Managing Performance in the New Frontier of Rich Internet Applications
GOLD SPONSORS:
ICEsoft
How Can AJAX Improve Homeland Security?
Isomorphic
Beyond Widgets: What a RIA Platform Should Offer
Oracle
REAs: Rich Enterprise Applications
Click For 2008 Event Webcasts
SYS-CON.TV
Top Links You Must Click On


More stupid PHP tricks
How to lock-down PHP-Nuke, make PHP a bit safer, & stop bad guys from touching MySQL.

(LinuxWorld) -- If you follow the latest security bulletins, you noticed someone discovered a huge security hole in the PHP-based weblog software PHP-Nuke. I mention this because I've been learning PHP the hard way by modifying the PHP-Nuke source code, since my two non-profit sites VarLinux.org and Petreley.org are based on PHP-Nuke. I used the 4.4.1a version of the source code, but it looks to me like the security hole may still exist in the latest version.

The problem exists in the admin.php file. This part of the program authenticates you as an administrator before it lets you run most privileged functions. There's a snippet of code outside of the security check that lets you upload a file. If you're clever enough to form the proper URL, you can trick PHP-Nuke into uploading its own PHP-Nuke configuration file as a text file. Then you can view the text file to find the password for the PHP-Nuke database.

The example used by the person who discovered this hole converts the configuration file into a file called hacked.txt. This wouldn't have worked on my system, since my Apache configuration would redirect a request for a .txt file to the home page. That's a minor detail -- you could rewrite the crack to create a file called hacked.gif instead, which is a file my installation of Apache would allow you to view.

There are a number of ways to fix this hole. The simplest is to move the code inside of the portion of the file that checks to see if you're an administrator before it allows you to do anything. But I ripped out the code, along with the other file manager functions within PHP-Nuke. I never use them, anyway.

Security tricks

Which brings me to my next stupid PHP tricks. One of PHP's biggest weaknesses is its use of global variables. Or, I should say, one of the ways you can invite security problems is if you enable and use global variables in PHP. You can turn off the capability altogether before you even start a project, thus protecting yourself from your own folly. The problem is most existing PHP code, including PHP-Nuke, relies on global variables. I would have to invest a massive amount of effort rewriting the PHP-Nuke code to get to a point where I could turn off the use of global variables.

For example, combine global variables with HTTP forms or cookies, and you've got a recipe for disaster. For example, PHP detects and addresses cookies automatically. PHP-Nuke sets an administrator cookie using the name admin. Once the cookie exists, PHP can access the contents of the cookie automatically as the variable or array called $admin.

Assuming only a true administrator can log in as an administrator, the only time this cookie should exist is if the user has been validated. This means you should be able to write this following simple bit of code to check to see if the user is an administrator (obviously, the "Do administrator stuff" is not real PHP code):

if (isset($admin)) {
  (Do administrator stuff)
}

If the cookie exists, then the variable $admin will be set. If the cookie doesn't exist, it won't be set.

Unfortunately, all a cracker has to do to get past this check is to append the string admin=1 to any URL on the site. PHP sees this in the URL string and sets a global variable called $admin to the value 1. That's all it takes to get past the so-called security check above.

I've implemented a solution that, while not infallible, still leans toward paranoia. It is an extension of the way PHP-Nuke works normally. (The PHP-Nuke code may have had that outrageous hole above, but it didn't do the simple $admin check in my example above.) PHP-Nuke stores the administrator ID number and password as part of the $admin cookie, so my code checks the password in the cookie against the one in the database every time you try to access an administrator task. In addition, it also checks your IP address against a list of acceptable IP addresses. Here's a simplified version of the code:

$admintest = 0;
if (isset($admin)) {
   $admincheck = base64_decode($admin);
   $admincookie = explode(":", $admincheck);
   $aid = "$admincookie[0]";
   $pwd = "$admincookie[1]";
   if ($aid=="" || $pwd=="") {
      setcookie("admin", "", time() - 3600);
      unset($admin);
   } else {
      $result=mysql_query("select pwd from admin where aid='$aid'");
      if(!$result) {
         setcookie("admin", "", time() - 3600);
         unset($admin);
      } else {
         list($pass)=mysql_fetch_row($result);
         mysql_free_result($result);
         if($pass != $pwd) {
            setcookie("admin", "", time() - 3600);
            unset($admin);
         } else {
            $ip = getenv("REMOTE_ADDR");
             $ahost_result = mysql_query("select ipaddress from adminhosts where aid='$aid'");
             if ($ahost_result) {
                while (list($ipaddress) = mysql_fetch_row($ahost_result)) {
                    if ($ip == $ipaddress) {
                       $admintest = 1;
                       break;
                    }
              }
              mysql_free_result($ahost_result);
              if (! $admintest ) {
                 setcookie("admin", "", time() - 3600);
                 unset($admin);
               }
            } else {
               setcookie("admin", "", time() - 3600);
               unset($admin);
          }
       }
   }
}

See what I mean about paranoia? It even cancels the cookie if the validation fails. The key here is I set the variable $admintest to 0 at the beginning. That way no one can override the check by adding the string admintest=1 to a URL.

The .php exploit

Another way to crack a PHP-based site, especially an open-source one, is to examine all the PHP files to see if the author left open any means of dynamically creating or changing a file, or even dynamically generating a database query. Then all you have to do is figure out how to form a URL to access that PHP file with your own variables. For example, suppose you create a PHP file called crackme.php containing the following:

<?php
mysql_pconnect($dbhost, $dbuname, $dbpass);
mysql_select_db("$dbname");
mysql_query($query);
?>

On the surface, it looks like it serves no useful purpose because we haven't set any of the variables the file needs. People create files like this because they function fine as generic subroutines. All you have to do is include this kind of file in another PHP file that set the proper variables, first.

Unfortunately, this practice opens a huge security hole for crackers. All a cracker has to do is create a URL such as the following: http://somesite/crackme.php?dbhost=databasehost&dbuname=username... etc. That way the cracker executes the file directly with whatever variable settings he or she wants.

One way to avoid this kind of problem is to seal up all your PHP code within PHP functions and make sure your code calls those functions properly. But it always helps to put something like the following at the beginning of every PHP file that you create to include within another PHP file, but don't want anyone to execute on its own. In the case of the crackme.php file, you would put this line at the top:

if (eregi("crackme.php", $PHP_SELF)) { die }

This checks the name of the PHP file currently executing. If it is crackme.php, then the program dies before it gets to the database code, because you didn't intend for anyone to execute this file on its own. If it is included in some other PHP file, then the $PHP_SELF variable will be something other than crackme.php, and the program will continue to execute.

This is the way PHP-Nuke handles all of the separate administrator files. One master file, admin.php, includes several other PHP files that manage stories, links, polls, and so on, such as stories.php, links.php, polls.php. Each of the separate PHP files assigned to these tasks checks first to make sure they're included within admin.php, otherwise they refuse to work.

MySQL, not yours

Finally, assuming you've nailed down your PHP code such that nobody can execute their own database queries on your system, you can also make sure nobody can access your MySQL database even if they do get the proper username and password.

If you use MySQL network clients on your local network but don't need to access MySQL from the Internet, close the port MySQL uses, port 3306, at your firewall. If you use MySQL for your Web site alone, and you have both MySQL and Apache running on the same machine, then you don't need the network client capability. Turn off all network access in MySQL itself. This is the default configuration on Debian systems, but you can do this on any system by including the string skip-networking under the [mysqld] section in your my.cnf MySQL configuration file. Or, you can use the --skip-networking command-line switch when you start MySQL.

By the way, the VarLinux.org code is GPL and you can download all of the code from the Downloads section of VarLinux.org. I'll warn you, though, that although you may learn something by studying it (even if what you learn is I'm often a lousy programmer), I cannot support the code, and I do not recommend you try to use my code in its current state as an alternative to PHP-Nuke to set up your own site. I made a number of changes to the database structure, but not in a way to install it for generic use. The only way to use the code now is to reverse engineer it to figure out how to create and populate the proper database tables, and that's not easy.

If you want to start a similar site, I recommend instead you start with PHP-Nuke 5.2 yourself, or one of the other offshoots of the PHP-Nuke code such as Postnuke. If you want to sample the many alternatives, visit PHP.net or Freshmeat and search for "weblog", or "blog."

About Nicholas Petreley
Nicholas Petreley is a computer consultant and author in Asheville, NC.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

If you're worried about PHP's global variables, just check for $admin using $_COOKIES["admin"] which cannot be set by the URL ?admin=1.


Your Feedback
Al McNicoll wrote: If you're worried about PHP's global variables, just check for $admin using $_COOKIES["admin"] which cannot be set by the URL ?admin=1.
Enterprise Open Source Magazine Latest Stories . . .
Grid Dynamics, an eCommerce technology solutions company, and GridGain Systems, makers of an open source in-memory platform for Big Data processing, on Wednesday announced the expansion of their partnership which began in 2008. Grid Dynamics provides personalization and big data solut...
Before embarking on using open source cloud technology for your web property, a basic understanding of cloud, as it’s used in the industry, is essential. While there might be exceptions, here are the definitions. A software application delivered on the web instead of installing standa...
Private clouds solve many problems for enterprises and bring unique operational challenges along with them. There are dozens of companies of all sizes that will build you a private cloud and turn over the keys – then what? Trying to convert a traditional enterprise IT operations team t...
The networking industry has gone through different waves over last 30+ years. In the ’80s, the first wave was all about connecting and sharing; how to connect a computer to other peripheral devices and other computers. There were many players who developed technology and services to ad...
If your organization already uses virtualized infrastructure, you are well on your way to providing IT as a Service. But as businesses demand faster results in today’s competitive market, organizations look to gain more benefits from cloud computing than just virtualized infrastructure...
In this CTO Power Panel at the 10th International Cloud Expo, moderated by Cloud Expo Conference Chair Jeremy Geelan, industry-leading CTOs & VPs of Technology will discuss such topics as: Which do you think is the most important cloud computing standard still to tackle? Who should...
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON Featured Whitepapers
ADS BY GOOGLE