Welcome!

Linux Containers Authors: Yeshim Deniz, Liz McMillan, Zakia Bouachraoui, Elizabeth White, Pat Romanski

Related Topics: Linux Containers

Linux Containers: Article

Two stupid PHP tricks

Seemingly insignificant, but important, details to help you run PHP successfully

(LinuxWorld) -- In the face of a slowing economy, it is increasingly difficult to justify spending any time working on my non-profit site VarLinux.org. I posted a notice stating there will be no further progress. Yet even after making it "official," I can't seem to stop myself from working on the site. Perhaps I have some secret hope it will blossom into a successful project that makes money instead of sucking the food out of my children's mouths. Or perhaps I find it therapeutic in these trying times.

Regardless, working on this site continues to be educational, particularly in when it comes to learning from my mistakes. (Whenever I think of that expression, I am reminded of the Peanuts strip where Charlie Brown says something along the lines of, "If it is true that you really learn from your mistakes, that makes me the smartest person in the world.")

I chronicle much of what I experience as it happens on VarLinux.org. But for the sake of my LinuxWorld readers and VarLinux.org readers alike, and to dispel any notion that I'm a master programmer, I will condense some of the most important lessons here. I've got reams of lessons I've learned regarding MySQL, Apache, and other pieces of the site, but I'll start with some of the places where I stumbled (or had to deal with the undesirable coding practices of others) while using PHP.

PHP lesson number 1

First, if you program in PHP, always use echo "text, variables, and html goes here"; instead of interspersing HTML and other displayed text with PHP commands. In other words, every ".php" file should begin with "<?php" and end with "?>" and never break away from PHP programming mode anywhere in-between.

This is the opposite of the way people tend to get started with PHP. They take their HTML files and insert some PHP commands here and there as necessary, breaking away from the HTML when they need the functionality PHP provides.

Even though that seems like a sensible way to get started, take my advice, even if you want to create a project based on existing HTML files. Wrap your existing HTML in echo statements, even though this means you'll have the tedious job of making sure all your double-quotes are preceded by a backslash. In other words, this...

<A HREF="http://wherever.domain">link text</A>

converts to...

echo "<A HREF=\"http://wherever.domain\">link text</A>";

The same goes for every other instance where quotes exist in your HTML. And remember that if you want your HTML to conform to the w3c standard, there are many places where you need to use quotes even if you can get away without using them. Most browsers aren't picky about such things these days, so it is tempting to leave out quotes where the HTML specification says you should use them. I'm a standards kinda guy, so I say use them just because you are supposed to use them.

I wouldn't be surprised if I hear from PHP programmers who tell me the above practice will have a negative affect on performance. It may, it may not. I have no idea, because I don't know how much overhead (if any) you are adding to your site when you make the PHP module parse echo statements rather than pass plain HTML through to Apache. But after having modified the code for VarLinux.org for the past couple of months, I can tell you it is a whole lot easier to maintain a site when you assume everything on the page is PHP. Use echo to send HTML to the browser.

Just one more note to satisfy the PHP gurus who are no doubt breaking out in a rash due to my focus on the echo command alone. It's true there's more to life in PHP than echo. For example, as you learn PHP, you'll find you don't need to use echo for every line of HTML. You can accumulate multiple lines, assign them to variables, use printf formatting, and then echo that output, for example. And you can use things like output buffers to play tricks and make your site more efficient (see the command ob_start() in the PHP documentation for an introduction to this technique).

My point is your should stay in PHP from start to finish if you want to make it easier to maintain your site down the road.

Stupid PHP trick number 1

In addition, make sure there are no blank lines above or below these two PHP opening and closing tag markers, "<?php" and "?>", respectively. If you follow this rule as well as the one about never breaking away from PHP, your server will never send anything to a visiting browser unless you have instructed it to.

This is extremely important if you ever expect to use cookies or redirect a visiting browser to a new location. If the PHP compiler/interpreter sees a blank line in a file outside of any PHP tags, it assumes it should send the blank line(s) to Apache immediately.

Once this occurs, Apache assumes it has sent the header for your page and you can no longer use the functions that manage cookies or redirect browsers to new locations. You can check for this condition with the PHP headers_sent() command. If it is true, then it's too late to set a cookie or redirect the browser with the PHP Header("Location: newlocation") command.

The easiest way to trip up on this particular rule is to include another file that has blank lines. For example, your hello.php file may read something like the following:

<?php
include("configvars.php");

function dosomething() { setcookie("thiscookie","thisinfo",time() - 3600); echo "Hello"; }

dosomething();

?>

If configvars.php has any blank lines outside of PHP tags, then you have unwittingly created the condition where headers_sent() is true, even if your hello.php file has no blank lines outside of the PHP tags and hasn't used any functions or variables from the included file. The setcookie() command in the function dosomething will fail simply because there was a blank line outside of PHP tags in the included file.

Stupid PHP trick number 2

I can't take the blame for how this stupid trick affected VarLinux.org, since the problem emerged from the way PHP-Nuke 4.4.1a was coded (I haven't checked to see if later versions of PHP-Nuke correct this). But the lesson I learned is simple. Always specify both arguments for the crypt() function. The first argument is the string you want to encrypt, and the second argument is the salt, which is something like the "key" to the encryption scheme.

The crypt() function is a one-way encryption technique that is useful for storing user passwords. You can't decrypt anything you encrypted using crypt(). (You might be asking yourself how such a function could possibly be useful, but we'll get to that in a moment.)

PHP provides other encryption functions that allow you decrypt what you encrypted. But I like using crypt() for storing VarLinux.org passwords because it provides my users with more privacy. If you use this function, not even the administrator can decrypt a user's password. If someone uses an embarrassing string of text, I can't find out what it is.

More important, it is difficult to figure out any VarLinux.org user's password even if a bad guy gains direct root access to the VarLinux.org server. If a VarLinux.org user's password includes any information that might help a cracker break into that user's own system, this technique makes it almost impossible for anyone to exploit information in the VarLinux.org database for such a purpose, even if they gain access to these passwords.

The crypt() function takes one or two arguments and returns the encrypted string. The first argument is the text that you want to encrypt. If you do not provide a second argument, crypt() will choose the default encryption algorithm from the following list (according to the PHP documentation):

  • CRYPT_STD_DES - Standard DES encryption with a 2-char SALT
  • CRYPT_EXT_DES - Extended DES encryption with a 9-char SALT
  • CRYPT_MD5 - MD5 encryption with a 12-char SALT starting with $1$
  • CRYPT_BLOWFISH - Extended DES encryption with a 16-char SALT starting with $2$

If you provide a second argument, crypt() will use the encryption scheme that matches the type of salt you provided as the second argument.

As I said earlier, the salt is like a key to the encryption algorithm. It is what the encryption algorithm uses to encrypt your text. If you use the crypt() function with only a single argument, it creates its own salt automatically, according to the default algorithm it has selected. Then it outputs the encrypted string. The first portion of that encrypted string is the salt that it used. This is what makes this function useful for storing passwords.

Here's how it works. (This example is entirely bogus and is meant only to illustrate the way the function is used in practice). Suppose you enter "password" as your password. VarLinux.org encrypts "password" with the crypt("password") function, which returns the string "2j38sn3km4", which is what VarLinux.org stores in its database for your password. We didn't specify any salt, but since we know the default encryption technique is standard DES, we know the first two characters of the encrypted output string comprise the salt for the string, because that's how standard DES works.

Assuming the first two characters of this string, "2j", comprise the salt, we now have a way to validate you as a user without having to know your actual password. The next time you log in, you will type the word "password". The VarLinux.org PHP code will then use your login name to find your encrypted password string, "2j38sn3km4". It extracts the first two characters, and attempts to re-encrypt your password with the following function: crypt("password","2j").

Notice this time we specify the salt as the second argument. Since you are using the same password, "password", and since the crypt() function is using the same salt it automatically created when it encrypted your password in order to store it in the database, it should create the same encrypted string again now. The two encrypted strings match, and you're validated.

The problem

Suddenly VarLinux.org users complained they couldn't log in again after changing their password. As a shot in the dark, I looked at the encrypted password strings in the database, and noticed some were much longer than others.

At some point while updating software on my server, PHP stopped using standard DES as the default for the crypt() function and started using MD5 encryption instead.

The mismatch arose from PHP-Nuke 4.4.1a specifing the first two characters of your encrypted password as the salt when you log in. In other words, it forces crypt() to use standard DES when it validates you at login. But PHP-Nuke 4.4.1a leaves out the salt as the second parameter when it creates your first password, or when it allows you to change your password.

As long as PHP defaulted to standard DES, there was no problem. But when PHP started using MD5 as a default, it started storing MD5-encrypted passwords in the database whenever someone would create a new password or change an existing one. The problem is the code continued to try to validate these encrypted strings as standard DES when you tried to log in.

If you take my advice above and always specify the second argument for crypt() whenever you use it, this mismatch will never occur. That's how I fixed the problem. Whenever anyone creates or changes a password, my code now calls a routine that generates a random two-character salt. It specifies this salt as the second parameter of the crypt() function, which forces crypt() to use standard DES at all times. No mismatch. No more failed login attempts.

Here is the makesalt() function, which I simply lifted from the comments section of the online PHP manual. There are better salt generators than this, but if you are truly concerned about security I recommend you base your site on MD5 or better instead of standard DES.

function makesalt() {
  srand((double)microtime()*1000000);
  $saltseeds =
  array('.','/','0','1','2','3','4','5','6','7','8','9',
   'a','b','c','d','e','f','g','h','i','j','k','l','m',
   'n','o','p','q','r','s','t','u','v','w','x','y','z',
   'A','B','C','D','E','F','G','H','I','J','K','L','M',
   'N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
  return $saltseeds[rand(0,63)] . $saltseeds[rand(0,63)];
}

More Stories By Nicholas Petreley

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

Comments (1)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


IoT & Smart Cities Stories
Dion Hinchcliffe is an internationally recognized digital expert, bestselling book author, frequent keynote speaker, analyst, futurist, and transformation expert based in Washington, DC. He is currently Chief Strategy Officer at the industry-leading digital strategy and online community solutions firm, 7Summits.
Digital Transformation is much more than a buzzword. The radical shift to digital mechanisms for almost every process is evident across all industries and verticals. This is often especially true in financial services, where the legacy environment is many times unable to keep up with the rapidly shifting demands of the consumer. The constant pressure to provide complete, omnichannel delivery of customer-facing solutions to meet both regulatory and customer demands is putting enormous pressure on...
IoT is rapidly becoming mainstream as more and more investments are made into the platforms and technology. As this movement continues to expand and gain momentum it creates a massive wall of noise that can be difficult to sift through. Unfortunately, this inevitably makes IoT less approachable for people to get started with and can hamper efforts to integrate this key technology into your own portfolio. There are so many connected products already in place today with many hundreds more on the h...
The standardization of container runtimes and images has sparked the creation of an almost overwhelming number of new open source projects that build on and otherwise work with these specifications. Of course, there's Kubernetes, which orchestrates and manages collections of containers. It was one of the first and best-known examples of projects that make containers truly useful for production use. However, more recently, the container ecosystem has truly exploded. A service mesh like Istio addr...
Digital Transformation: Preparing Cloud & IoT Security for the Age of Artificial Intelligence. As automation and artificial intelligence (AI) power solution development and delivery, many businesses need to build backend cloud capabilities. Well-poised organizations, marketing smart devices with AI and BlockChain capabilities prepare to refine compliance and regulatory capabilities in 2018. Volumes of health, financial, technical and privacy data, along with tightening compliance requirements by...
Charles Araujo is an industry analyst, internationally recognized authority on the Digital Enterprise and author of The Quantum Age of IT: Why Everything You Know About IT is About to Change. As Principal Analyst with Intellyx, he writes, speaks and advises organizations on how to navigate through this time of disruption. He is also the founder of The Institute for Digital Transformation and a sought after keynote speaker. He has been a regular contributor to both InformationWeek and CIO Insight...
Andrew Keys is Co-Founder of ConsenSys Enterprise. He comes to ConsenSys Enterprise with capital markets, technology and entrepreneurial experience. Previously, he worked for UBS investment bank in equities analysis. Later, he was responsible for the creation and distribution of life settlement products to hedge funds and investment banks. After, he co-founded a revenue cycle management company where he learned about Bitcoin and eventually Ethereal. Andrew's role at ConsenSys Enterprise is a mul...
To Really Work for Enterprises, MultiCloud Adoption Requires Far Better and Inclusive Cloud Monitoring and Cost Management … But How? Overwhelmingly, even as enterprises have adopted cloud computing and are expanding to multi-cloud computing, IT leaders remain concerned about how to monitor, manage and control costs across hybrid and multi-cloud deployments. It’s clear that traditional IT monitoring and management approaches, designed after all for on-premises data centers, are falling short in ...
In his general session at 19th Cloud Expo, Manish Dixit, VP of Product and Engineering at Dice, discussed how Dice leverages data insights and tools to help both tech professionals and recruiters better understand how skills relate to each other and which skills are in high demand using interactive visualizations and salary indicator tools to maximize earning potential. Manish Dixit is VP of Product and Engineering at Dice. As the leader of the Product, Engineering and Data Sciences team at D...
Dynatrace is an application performance management software company with products for the information technology departments and digital business owners of medium and large businesses. Building the Future of Monitoring with Artificial Intelligence. Today we can collect lots and lots of performance data. We build beautiful dashboards and even have fancy query languages to access and transform the data. Still performance data is a secret language only a couple of people understand. The more busine...