PHP

18 Mar 2006

Recovering encoded php files

And now for something normal .... back on PHP land....

Someone posted a comment on a post I did a while back about a product that was supposed to provide encryption on PHP scripts. (That blog post was probably my most controversial, as the author of the application send me an email asking me to contact his lawyers....)

The post this time was about another magic cure, php recovery, a new web site claiming (or appearing to) sell a product to recover php source code after it has been encrypted. Well, considering my last post, using plain old PHP methods, this is perfectly feasible. However they also claim to restore your code if it was encrypted with ioncube and Zend's encoders, which, not having tried them, but knowing the author of both products reasonably well, I have a few doubts about.

Well, for the uninformed, the basic premise of Zend encoder and ioncube (as far as I know) is the same as bcompiler, which I created based on some of the code in APC. Basically the idea is to deal with the bytecodes that PHP creates. For a normal file, this would be function, class definitions, and raw code. (although conditional classes are a bit complex from my recollection)

Looking at the basic premise of converting these bytecodes back into PHP, while it is definatly feasible, there would be significant limitations to the end result.
  • uncommented! - if any of the encodes obsfucate the variable names or function names on compilation, you are in real trouble here..
  • layout and formating. - no whitespace or formating by a programmer..
  • optimizations my modify the code - chances are after decompiling it, a few bytecode optimizations would have occured, often making the code even more difficult to understand.
If you want to play with a potential decompiler, have a google for Derick's VLD, this can dump the opcodes to a readable format, from there, it's not totally impossible to create the code from it.

What always strikes me is the whole issue about bytecode compilers, when I wrote bcompiler originally, One of the reasons was to protect the source, however, this protection is totally superficial, and probably only valid in the 'try-before-you-buy' market. (Which in our case was going to be giving embedded linux boxes with compiled PHP code on them). Even that in hindsight was a very questionable use. I would be extremely wary of using any code that was encoded on a mission critical project. Lag times for response, and long term support risks are just too big to consider anyone providing encoded source. (on the other end, dont deliver all the code without even a deposit! - especially to questionable dotcoms...)

As for our mysterious php recovery application, If this guy is serious, he should at least fill out a valid domain registration details for whois. Sorry 12345689 in JAPAN doesnt look much like a valid telephone number to send your money to....

Posted by in PHP | Add / View Comments()

15 Jan 2006

smart_str API

Well, for a change, a vaguely usefull blog post ;) - I was sitting down looking at the DBDO code, that I got ivan to look at a few months ago. Being a gtk guy, he had copied the gstring api into DBDO, which from my recollection of the PHP internals is pretty similar to smart_str. However, there is no documentation for smart_str, other than the source. So here is a first go at it....

** feel free to make comments / correction notes.

SMART STRING API

from:
#include "ext/standard/php_smart_str.h"

The Struct:

    typedef struct {
char *c; // data goes here..
size_t len; // the current length
size_t a; // the allocated size
} smart_str;
EXAMPLE:
    smart_str *sstr;
sstr = emalloc(sizeof(smart_str));
smart_str_sets(sstr, strdup("")); // start it clean.
.....
smart_str_free(sstr);
    smart_str sstr = {0};
smart_str_alloc(&sstr, 100);
smart_str_sets(&sstr, strdup("This is a string"));
smart_str_free(&sstr);

If you are setting up a pointer to the smart_str, it's probably best to use the _sets method, to fix the memory

Creating Memory:

    void smart_str_alloc(smart_str *str, int len, int is_persistant);
EXAMPLE:
    smart_str *sstr;
sstr = emalloc(sizeof(smart_str));
smart_str_alloc(sstr, 100);

Note: This only allocates memory for the string inside the smart_str, if you are using a pointer to the smart_str you must still emalloc that.

Initialize:

     void smart_str_sets(smart_str *dest, char *src); 
EXAMPLE:
     smart_str *sstr;
sstr = emalloc(sizeof(smart_str));
smart_str_sets(sstr, strdup("This is a string"));
Note: this does not copy the string (so freeing the string after using this will likely resulting in a double free error

This is usefull when working with a pointer to the smart_str, where you can not initialize it as empty.

Closing a String

    void smart_str_0(smart_str *str);
EXAMPLE:
    smart_str *sstr;
sstr = emalloc(sizeof(smart_str));

smart_str_appends(sstr, "Hello World");
smart_str_0(sstr);
printf("the string is %s", sstr->c);

Note: If you need to pass the string to a function that accepts \0 deliminated strings, you should use this function.

Add a Character to a string

    smart_str_appendc(smart_str *dest, char c)
EXAMPLE:
    smart_str *sstr;
char c = "C";

sstr = emalloc(sizeof(smart_str));
smart_str_appendc(sstr, c);

Notes: do we need to pre-allocate the string in any manner?

Add a string

    smart_str_append(smart_str *dest, smart_str *add);
smart_str_appends(smart_str *dest, char *add);
smart_str_appendl(smart_str *dest, char *add, int n);
EXAMPLE:
    smart_str sstr1 = {0};
smart_str sstr2 = {0};
smart_str sstr3 = {0};

smart_str_appends(&sstr1, "the cat");
smart_str_appendl(&sstr1, " the dog", 3);

smart_str_appends(&sstr2, "the cat");
smart_str_appendl(&sstr2, " the dog", 3);

smart_str_append(&sstr3, &str1);
smart_str_append(&sstr3, &str2);
Notes:
appendl: adds only the first n characters to the smart string.
appends: adds the new string to the smart string (assumes \0 terminated.

Adding Numbers to a smart string:

    smart_str_append_long(smart_str *dest, long val);
smart_str_append_unsigned(smart_str *dest, unsigned long val);
smart_str_append_off_t(smart_str *dest, off_t val);
EXAMPLE:
    smart_str_append_long(sstr, 120);

Free the String:

    smart_str_free(smart_str *str);
Example:
    smart_str *sstr;
sstr = emalloc(sizeof(smart_str));
smart_str_sets(*sstr1, strdup("the cat"));
... do something ...

smart_str_free(sstr);

See Also:

autoallocating sprintf. (with \0 terminated added)
    snprintf(char *buffer, int max_size, char *format, .....);

Posted by in PHP | Add / View Comments()

28 Oct 2005

Frameworks, Frameworks, more than you ever wanted

While speculation is rife over Zend's new almost vapourware, I sit and wonder where it is going. What can you add to the mountains of comments that have preceded this release. I even wonder if Zend are playing their old favourite Microsoft game of hiring the competition.

Frameworks are an odd component of programming, for a change, this week slashdot published a link to a very relivant article, detailing how in some respects Graphical Development enviroments enable API writers to go crazy and create bloated libraries, which are solved by spiffy features in the editor (make you think of ZDE?). Yet dont address the fundimental issue that the API was fat and nasty to begin with.. From the quick look at Wez's post, that is one of my suspicions for the Zend framework.. but you can hardly comment on something that is not there...

Writing small clean API's is an ongoing challenge, And while PHP5 offers many new features, Having coded a few hacks in it, I begin to feel like it is persuading me to go down the bloated API route. While PHP4's object model may be regarded as a pain, defaulting to cloning objects is actually rather handy in 9 out of 10 situations..

To me a pear provides about the best you can get for frameworks, (ignoring the fact that a pageloader is not included) as it provides small re-usable components, that are in generally well looked after, and improved over time. (look at my libraries in there, some just had their 3rd birthday).

There is something about having a single source of code libraries provided and sponsered by companies (who are larger than the rest of us), smacks of the .NET/Java mess, where you spend more time reading about the obtuse class libraries, than understanding the code you are fixing.

One thing I find annoying about the justification for Zend's Framework is the IP FUD, calling a spade a spade, IP issues around libraries is not that complex.. - As long as you avoid GPL code in non GPL projects, for the most part you should be ok.. - hardly something that needs to involve 22 layers of lawyers..

At the end of the day, I guess I'm not the target audience for such a framework... - It's probably more aimed at the clueless IT department manager, who see's big names behind a library and assumes it's good, (sound like a MS/Sun strategy?) rather than letting the project architect decide on an approach and trust in their judgement....

Posted by in PHP | Add / View Comments()

20 Oct 2005

FlexyBugs - php.nets bug system rebuilt

One of my non-PHP related projects is nearing client delivery this week, and like most software projects, It's bound to have bugs. Normally I just deal with this by email's or a gnumeric spreadsheet, but since this project is a bit more complex than others, I decided a bug tracker might be a good idea..

So in the true spirit of "it's not built here", I started hacking on the php.net bug system. Well, less of hacking, more of copy the database schema, and HTML and replace all the PHP code with nice clean object responses, based around FlexyFramework.

The end result is about 90% of the current features of php.net's bug tracker with a few new ones added:

From the package description here's the details:


This is a re-write based loosely around the php.net bugs system. Uses The FlexyFramework logic to make a simple to understand,yet extremely powerfull, and hopefully pretty safe bug system

Standard PHP.net features
  • report bugs
  • email out comments / reports / updates
  • search bugs
  • view bugs
  • edit bugs
  • developer update bugs.
  • add comments to bugs

Additional Features
  • File upload for patches/screenshots/documents etc. (for authenticated users only)
  • Optional Authenticated bug reporters
  • Private Projects / Bugs / Comments etc. (only available to Authenticated reporters)
  • User groups : Administrator (add users), Developers (change projects/bugtypes etc.) And users - who can report and upload users.
  • Change logging in bug report of fields changed.
URLS:

Posted by in PHP | Add / View Comments()

13 Sep 2005

Code encryption = funny solutions

Someone just emailed me to comment on something called phpcodelock, (google for it, I'm not going to advertise stupid products)..

It's always funny to see people try and encypt PHP source (or javascript/html for that matter.) As the reality is, encyption is only any good when the end user doesnt get hold of all the keys to open the door.

I've no idea how exactly the product above works (but I'm 100% sure it's not really going to work beyond a superficial look). But it looks similar to another funny effort I saw the other day. Someone used eval(base64_encode(".....")); - which basically had 10-16 nested calls to eval(base64_encode()) inside the data.. = a quick preg while loop on the code solved that one..

So to try and stop stupid people spending (or losing their) money on stupid products, here's a hackers guide to reading encypted PHP code

Step 1: open up the php source code (the one you download from php.net), look for any of the zend engine that parses PHP source, and stick a big printf() ( optionally to a file somewhere..) just before it's parsed.!!!!!!

Opps - that's it (there is only one step!) - almost all encryption methods fall foul of this.!!

Actually the reason someone asked me was because I hacked the apc source into bcompiler quite a few years ago, and since then Val Khokhlov has been doing an excellent job, fixing all my bugs, adding features and making it work with PHP5.

bcompiler does work to some degree as a encyption technique, as you would have great difficulty resurecting the original source code from the opcodes (although you could get something resembling the source out, with alot of work...).

But really, why bother... that's what copyright is for.!! The only justification I can imagine (having seen the crap hidden behind this stuff) is to hide away some horrifically bad code, that the Author was so embarressed to show to the world..
Posted by in PHP | Add / View Comments()

25 Aug 2005

Six deadly PHP sins, this week...

Fixing someone else's code is frequently the most annoying job that anyone with some intellegence has to do. It's one of those, pay the rent, scream and run around jobs..

I'm sure other languages suffer as well, but thanks to PHP's learning curve, software written in the language often falls into 3 categories
  • Half a clue (HAC)
  • Reasonably worked out
  • Over engineered
This week, unfortunatly, I had to attack both the HAC and the Over engineered, (not on the same project thankfully).

The problem with the HAC project was the end users had found a few minor bugs. (this was a PHP application that had been paid for by a client - kind of like a shareware type thing.). But luckly (or perhaps less luckly for me) they got the source code.

Bugs are a fact of life for all software, whether you find them when developing, or as an end user. There's bugs in all my software or features depending on how you look at it (see the bug list on pear.). But the difference between average and good programmers (IMO) is the ability to write code that someone else has a chance of understanding.  (and sending in bug fixes...hint hint....)

Untraceable code paths.
The first gripe I had with the HAC was the horrific use of random functions included from a wealth of files, making following the codepath next to impossible. (which file will this function come from? = grep again...)

The bug I had to solve was supposed to be quite simple the host name for an img src= tag, was pointing at the wrong server. (the application lives on a private development server running behind a reverse proxy, and hence the wrong host name)

Same code repeated in global scope
Like alot of PHP applications, this one had one script to respond to each url request (rather than a bootstrapper and class loader). The script then did the usual crap of loading config, libraries (bad joke there) etc. It then went down and had a big if block for each action.. (all in global scope). Apart from making the file rather large, it also would have made managing global changes to the site more complex. This is where this concept makes a world of difference.

class page_action extends applicaton_base { } 


Mixing PHP and HTML badly
Unfortunatly, no-where within that code was it immediatly clear where the image url or HTML was comming from. Yes another of those deadly sins, splattering HTML all over the PHP code,  resulting in some very large php scripts, which you have to look really hard to determine the what on earth is going on due to the excessive noise from the HTML..

HTML + Databases + $variables +  eval = trouble waiting to happen
When I finally tracked it down, (after grepping for a few functions that seemed possible candidates) I found that the tag was contained in a small snippet of HTML stored in the database. The HTML in the database went something like src="$site_base_url/$the_image_url". The author had decided that the wonderfully secure eval() function made a great dynamic layout tool.

Every variable should start somewhere
Now I knew what the variable was. The next task was to work out where it was comming from. A grep of the source indicated lots of instances of it being used, but not a single one creating it.

This is my pet gripe with $smarty->assignVal(), (and quite a few other template engines) you have another instance of data getting used with a great disconnect with the source of the original data.  Making backtracking code and locating where something occurred considerably more difficult. Let alone making security auditing next to impossible.

Global is almost as evil as eval()
Almost all the functions in the applications had a list of 20 or more global variables. This instantly made all the function completely un-re-usable. (it hard coded the implementation to the application). and goes back to the problem of tracking down where variables where created.

How may evil functions does PHP have - extract()
In the end, the culprit of this design was the wonderful function extract(), It had been used to convert the return array from a database query, and filled those wonderfull global variables. By making the result set array available globally the could would have been so much more readable, and it would only involve a small amount of extra typing (Copy and paste anyone). So after all that digging, It turned out you had to use the application interface to change that variable......

I guess in the end, this all goes back to the Microsoft philosopy, if we all made perfect software, then there would be no work for everyone fixing it. Although some of us would like to doing more with our lives ;)
Posted by in PHP | Add / View Comments()

28 Jul 2005

How to 0wn planet-php

Haha ;) - I changed the routine that generates the url for my feed, and planet-php is now 'my blog ;)'

I'm sure Christian will notice soon and get it back to normal.

[update] it looks like RSS 0.91 didnt really support pubDate (for entries), so almost all the feeds that come off of that are probably succeptable to the same issue (if you change the url).. - I've added <pubDate> to my entries - maybe that will help christian to sort out the mess, or better still just check to see if something with the same title already exists in the database.

[update2] Seems like some people may have forgotten their sense of humor.. - The url change was necessary as I had be creating broken urls in my rss feed (when I used ? & etc.).. - The fix accidentally forced planet-php to refresh (as it thought they where new urls') - This post is just a light reminder about why you are getting 'Alan' overload today.. ;)
Posted by in PHP | Add / View Comments()

28 Jul 2005

Why are we code nazis? and some php shops

There was an amusing comment on my PDO post today, exposing how they hate being told what is good and bad, by us code nazis.

In some ways I have to agree, I dont like being told what is good or bad.. - buy I do enjoy reading the pro's and con's (the Joel on software stuff about exceptions, and the responses on other blogs helped form a well rounded opinion on their potential use.) Although a few hard core exception projects will probably be able to clarify their best uses.

But this week has been the best illustration yet, about why I tend to rant on about good or better practices. I had a potential client requesting an online shop. Simple you may think. Just download one of those great free open source projects..

So I started with what looked like one of the more popular, OSCommerce (no I'm not going to link to it...!). To put it politely, "What a bunch of turd crap", I only got to the installation stage that came up with an error "please turn on register globals" to realize this was not even worth the time of day. - Hint one, dont code with register globals on!!!

Next up was Fishcart, another project I had played with many years ago. The trouble this one has is that the installation is so horrifically complex (they even have a crazy perl script to try and help you out) - How complex could setting up a shop be - create the database, change the db connections and make a folder to put uploaded files. Yet this one just refused to do anything resembling install.

Last up was phpShop, something I had noticed from my referer logs, as the developers had chosen to use quite a few PEAR packages (including my little DB_DataObject). The downloadable one is an old version, however the one in svn contains all the pear based code. It was also was pretty easy to set up and get working , after spending a bit of time messing around with configuration files.- making sure the path was correct (hint you can use php to determine that, you dont need a config var for it)

In general the code from phpshop was not too bad, however, I had a few requirements for my shop that would involve quite a bit of hacking  to phpshop's internals, so I had to dive into the code. Unfortunatly having chosen to use DataObjects, they did not appear to have used it properly! - the Dataobjects that had been created did not contain any code apart from the autogenerated stuff.. They appeared to have an extra layer of libraries doing all the things that should have been in the dataobjects.. They also had chosen not to use wysiwyg style templates, opting instead for a few PHP style ones, and alot of html embeded in the PHP classes.

So at the end of the day, the decission was to build my own (with a bit of help). The backend will be  XUL based, and front end will be heavily CSS and Flexy template based.. Licence and distribution unknown at this time.. - but it may be pretty restrictive!, so dont hold you breath for a free well coded, downloadable shop ;)

Posted by in PHP | Add / View Comments()

10 Jul 2005

Security, How not to react....

I'm not sure Paul has done himself many favours in his reactions this week. Security breaches happen all the time, either from relatively friendly testing, or more frequently actual breakins. He should be breathing a sigh of relief that the worst damage is having to run a SQL statement DELETE * FROM xxx where body like "%test_xss%"

Last year I blogged about one of my clients getting rootkit'ed, this is probably the worst of all Unix based disasters. And the lessons from that have to some degree been applied and acted on.
  • Keep up to date with security announcements (and schedule updates reasonably regularly
  • run chkrootkit on a cronjob (as debian's package does now)
  • Keep a good set of backups
  • Try keeping up a backup server (with replicates the main servers operations)
  • Practice taking the backup server live!
This year's issues saw yet more attacks, most common has been ssh port scanning and user testing. Looking at /var/log/auth.log, a few months ago I started noticing a huge number of failures on the main web server. And not just from one IP address. As a defensive measure I did one simple thing
  • Change the port that ssh runs on!
While this works well on my server, one of my main clients has also implemened ip based restrictions at the firewall level for ssh. So unless you are a registered IP address, you do not even get a prompt.

I had made this modification to a couple of boxes that I directly use, however It was not feasible for a number of others that i rarely touch.

Last month, I saw the result of what the ssh attackers had started doing. From the logs a Romanian IP had managed to log in a few times under the ftp account via ssh (An account that was probably briefly enabled when I set up ftp, but latter ended up using .htaccess style passwords for it), but had forgotton about. Obviously the password I had given that account had been less than secure, and they had managed to get a shell account.

Thanks to the wonderfull logging ability of Linux/Unix etc., I had a facinating history of what they had attempted (via the bash_history) and copies of quite a few of the files they used. (funnily enough they had to use the ftp home directory, which was a highly visable location to put .tgz files on a windows network!)

I guess partly by luck they had not attempted to rootkit the box, although the system was quite up-todate (tested via chkrootkit, and looking at the logs). They had however tried installing an irc server, and used the box as a scanner to find other vunerable ssh hosts. (the irc didnt work due to the user privages mixed with our firewall configuration.) I didnt examine the logs that much to see if they found any other vunerable hosts.

So what lessons came out of this one, - another run around check on the servers I look after
  • start using the AllowUsers line in the ssh file.
  • where feasible lock down ssh access to IP's at the firewall level
  • regulary check /etc/passwords to see who has accounts.. and shells.
  • regulary check /var/log/auth.log with grep to see who has been accessing (or trying to access the server)
In the same respects while the wiki at pear was being tested, I was on IRC with they people doing the testing, and was babling on how half the problem with pear and the wiki was that it used PHP as templates, (while not totally true, it is a big enough factor to make it a concern).

The real problem I had spotted months ago when fixing a report of another XSS attack on the pear site, was the disjoin between input and output. Variables where being set in one place, and used in another file, with no basic premise if they had been escaped or not. Something I had been ranting about, with only a few takers, when describing why template engines where valuable. The basic premise that all data should be untrusted and hence escaped, unless you expressly know it's ok... (rather than the other way round..!)

To say I'm a guru on this however would be twisting words, during the tests that where being run on pear, the testers, fired it off at my site, and one of my clients (at my request). The hole they found on my site was due to a error message not escaping input correctly (something I would not normally do, but had hacked up my own site a bit too hastely), however, it appears that most other attacts failed due to flexy's escaping, and maybe in part to the javascript defence on the comment system.

My client faired a little worse, as we had been using a very old version of the Pager library, which has since been updated, along with some rather silly mistakes that had been made with the url writing being done in PHP rather than the template engine.

But this is definatly not an invitation to try and hack my systems, but if you do, please dont rootkit them, as it's a royal Pain in the ass to fix!!!


Posted by in PHP | Add / View Comments()

04 Jul 2005

Conferences, the odd call for submissions

Every year PHP has two or three major conferences, as someone who knows a little bit about PHP, I often put in a proposal on the call for submissions. However, after presenting at a few, the whole process does seem a little odd.

PHP conferences are primarily commercial ventures, where the organizers costs (location, airfares, advertising etc.) are recouped by the attendance fees. However, the idea behind call for submissions, is something I would more often associate with academic type conference. The organizers tend to rely on the (usually very good) judgement of the reviewers of these submissions to decide what might prove interesting and attractive..

The conferences also have a secondary purpose of getting the PHP developers together, and frequently try and sort out some of the more interesting direction issues that some of the PHP projects are taking. (but this is almost never the primary goal of the conference for obvious financial reasons..)

What I end up wondering is what would the attendees actually like to hear about... What would make the costs associated with going to these conferences make them better value for money?

Interesting technical things like GTK, language internals etc. or more how to use a specific library, extension, a forum on where PHP is going... Or what was very succesfull at the PHP cruise a few years ago, a more interactive discussion about how to develop in PHP..

Feel free to comment away..
Posted by in PHP | Add / View Comments()
« prev page    (Page 3 of 7, totalling 63 entries)    next page »

Follow us on