03 Mar 2010

Reported Attack Site - recovering from gumblars

Just about finished a gumblar cleanup, for a small Hong Kong company. This is not the first crack I've seen in the last few months, I fixed another server last month that got ssh brute force attacked. It looks like cracking is on the up, so if you need help fixing a site, by someone who knows what they are doing, and at the same time you will help out a number of open source projects - give me a bell (

The gumblar (or derivative) attack I was looking at was quite interesting, the first indication the owner got was that browsers kept showing the "Reported Attack Site!" or "Warning: Visiting this site may harm your computer" message. So I get the call to find out what's going on.

When you ignore the message and go through to the site, look at the HTML the first thing you see is that there is a <script> tag added just before the body pointing to a gifimg.php file. After that you have a long hunt around google to find out what's going on.

At the time of writing, the exact attack vector does not look like it's been confirmed, but is either a brute force ftp attack (I think is quite unlikely considering the username/pass combo on this sample site). Or more likely a PDF desktop attack to a machine that has access to the site.

My first assumption was that it was a Wordpress exploit, but the more I examined the situation, it seemed less likely. However I highly suspect that the PDF attack vector having got the ftp credentials goes looking for standard locations of wordpress installations (eg. '/wordpress) - so hint one is not to install your software in such obvious places.

Cleaning it out

The first step in sorting out the mess was to mirror the original site, with virus and all onto a offline location. (both as a precaution that if we broke things we had a backup, and so we can use this as a source to replace the hacked files with new ones).

After that it was a matter of googling for details of the attack and writing a gumblar cleaner script. It basically checks for infected file types, then preg_replaces out the hacked additions. These include

  • php files with an eval/base64_encode line
  • javascript files with document.write lines
  • html, shtml and htm files with <script tags.

I used ftpput, and check return values, to ensure that each file was successfully replaced before overwriting the local copy and making a nice copy for my reference into the virus folder.

Inside out of the attack.

The infection is quite interesting, and in this case was quite painful, due to the nature of how Wordpress publishes files.

Initially I suspect the core code in the PDF actually has some ftp code which will try and modify standard set of PHP files to add a small base64_encode script.. (phplist, and wordpress appear to be core targets, and I'm sure there are more.)

This is a snippet of some of the code that get's added (it's all eval, base64_encoded - read up on my blog post about idiot ways to protect your PHP code using this idea.)

This is a snippet of the decoded script

function kqyf($s){

... infect the page stuff goes here...
function kqyf2($a,$b,$c,$d){
$s[]=array($a=='default output handler'?false:$a);
echo $s[$i][1];


After that wordpress does it's wonders and infects the rest of the site for you. As all the generated pages suddenly get the extra <script tags> when publishing and your wordpress outputs the infection into the admin system.

Note: I only dissected one of the php scripts, which changed output buffering adding the <script tag, but did not see the document.write changer. I suspect there may be another variant of the script above that i did not look at that modifies the javascript files, or that it's done remotely.

Anyway all cleaned up after a few days (due to the long time the original backup took) . After this the recommendations for the owner where, stop using adobe PDF viewer (there are alternatives out there) - stop using IE, ask all staff to use Firefox with noscript. and keep a backup!

Posted by Alan Knowles in PHP | Add / View Comments()

30 Mar 2008

Little mice squeek to much - feedback on some of the coding issues..

Have to admit the reaction online to some of these posts have been quite funny, Cake guys, don't take this so seriously.... - Most of what I said about Cake I pretty much stand by, the responses I've seen don't seem to show that they knew they where making compromises in designing it the way it is, rather they knew best, and live with it (or without it..)

.. I also wonder what I got myself into...

More muses on the responses.....

** Apologies to Planet D for the Abiword CSS in the RSS / might be worth using the D RSS feed for Planet D? **

Posted by Alan Knowles in PHP | Add / View Comments()

26 Mar 2008

CakePHP taking it apart, and the better written world of sinners..

Yeah, at one end we have our happy little hackers trying to make a quick CMS by throwing together a few includes and hiding functions everywhere in their wonderful directory structure, at the other we have those glorious frameworks.

So If you enjoy my rather questionable grammar, and High Horse views, here's the dig through CakePHP.

Dissent always welcome so comment away...

Posted by Alan Knowles in PHP | Add / View Comments()

22 Mar 2008

Another 7 deadly sins for PHP

Ok, Since I had some really bad seafood on Good Friday (hence not turning out to be that good). resulting in me vegitating in bed today, I thought considering how much crap I gave some of those CMS projects, they deserve a bit of an explanation about why they got nailed.

Otherwise known as the deadly sins re-run post...

Posted by Alan Knowles in PHP | Add / View Comments()

18 Mar 2008

Licence to release PHP code?

I sometimes wonder if people should apply for licences before releasing PHP code, I thought I'd have a look at the CMS's in the 'Lite' category of opensourcecms. Unlike most of the reviews you get, I was specifically looking at code quality. not fuzzy does it look nice!

Basically if I need to use any of this for a commerical project, the first question will be, can we maintain and add to it, knowing that it's going to be maintainable. Well. the basic answer from all of the code in the 'Lite' section is. Forget about it. Most of the code in that section, you would be lucky if you server was not hacked. Installing a virus might be more efficient..

Anyway this is the summary from looking at the code.. - it's not pretty and I've not got much in the way of complements for them.. - but it's quite entertaining...


BAD - Uses defines for configuration
GOOD - Bootstraper (index.php seems reasonably sensible)
BAD - Stupid directory layout
BAD - Namespacing on classes not sensible
BAD - re-written database abs. layer
BAD - stupid file naming *.class.php
BAD - loads of smarty assignvar's


BAD - functional based single file crap


BAD - site was hacked!
BAD - Code unreadable
BAD - include style running


BAD - uses functions everywhere
BAD - directories splattered with unorganized files.
BAD - Code unreadable
BAD - php Serialized data in Files pretending to be a database


BAD - Messy mix of HTML + PHP
GOOD - a bit of structure to it
BAD - horrific class naming sturcture.
BAD - uses capital letters for GLOBAL variables everywhere.
BAD - Functional crap


BAD - functional Crap
BAD - farcical mix of HTML and PHP


BAD - functional Crap
BAD - unreadable code
BAD - if .. if .. if ... interpreting of page actions..


BAD - Mix HTML and PHP
BAD - trys to get arround register globals!
BAD - functional crap


BAD - stupid licencing
BAD - stupid file naming *.inc
BAD - functional crap
BAD - mix HTML + PHP
BAD - unreadable code


BAD - losts of functional crap
GOOD - uses pear
BAD - mindblowingly bad filenaming
BAD - not lite or simple (WTF was it in this category for..)


BAD - not available


BAD - functional crap
BAD - stupid file naming standard - .mdu!!
BAD - mix HTML and PHP

Posted by Alan Knowles in PHP | Add / View Comments()

09 Mar 2008

Chinese Xapian search and indexing

its funny how you can often end up solving pretty much the same problem twice, dejavu for coding. Last weeks challenge was a free text search engine for email archives including support for chinese.

About 7 years ago, I remember hacking on mnogosearch to solve a pretty similar problem. After some research this time, I settled on Xapian, some of the reasons included,
- utf8 internal support
- nice bindings for PHP & c (via gcc/C++)
- a working set of command line tools (omindex & quest)
- database independant ~ no mysql dependancies
And the test that always makes the deal is that after apt-get'tting the package, it just worked! Creating a working store and runing queries is quite simple

The only trouble was that although it says it supports utf8, actual support for chinese is a bit more complex.

Unlike western langages, each character needs to be treated like a word. Ideally Xapian would realize this, however without wanting to hack the C++ code, I decided it would be quicker to create files based on the original email and pad the chinese characters with spaces. This means, in the short term, I can use omindex, rather than, binding the D code directly to xapian API.

the way this is done in the D index builder is
- parse the email with callbacks for each mime part. I have ported the mime code from binc imap for this, and called it dinc (silly name for the week)
- if the part is text, or html, convert it to utf8 using iconv
- stream read each line of the body (using memory streams)
- convert each line to utf32/dchars
- loop through the dchars and see if the are chinese, japanese or korean (see this for the simple check for cjk characters). pad the ouput line with spaces when found
- convert the resulting utf32 array to utf8/char array, and write it to the output stream (file stream),
all this code should be quite simple to extend when i get round to the d direct access to xapian api. It should also be pretty memmory efficient, and fast when i rewrite the iconv code to work like a stream filter...

On the other end of this was making the extjs/php5 front end do the searching. Again, the end user would be expected to search in chinese as a series of characters, eg. type 'XXX' rather than type 'X X X' so in php. I needed to convert the search string into utf32, and compare each block of 4 characters against the previous list of cjk charcters, padding with spaces. then converting back to utf8 prior to sending the query. This is all pretty simple using iconv or mb_string.

All in all, not that difficult to do, however actually finding/working how to do this was quite a challenge.

Posted by Alan Knowles in PHP | Add / View Comments()

10 Nov 2007

PHP's days numbered?

PHP's great claim to fame has always been a solution to a domain specific problem, Delivering Web pages. It's relatively easy mixing of HTML and code (while at times very nasty), have proved quite a good solution for many people.

But as technolgy moves forward, I wonder if PHP will be required much longer. Why you may ask, since I've got craploads of PHP code lying around in my subversion folders. Well In addition to most of my new projects using ExtJS to deliver the interfaces, which has almost totally removed PHP from rendering tasks. The last few weeks I have been using Mysql's newish Stored procedures, which move the alot of application logic and rules into the database, and seriously reduce rather kludgy code in PHP. Not only that it also reduces the data going back and forth between PHP and Mysql.

So PHP is doing less and less of the work, to the point where if there was an apache module that did mysql stored procedure calls based on the request URL, and returned JSON, I suspect PHP would be practically obsolite.....

Anyway started playing with apache modules today... - not enough time to do anything substantial, but there are a few fixes needed to this page.
The build lines should be something like this.

gcc -fPIC  `apxs2 -q CFLAGS ` -I`apxs2 -q INCLUDEDIR` 
-c time_cookie.c -o time_cookie.o
gcc -shared  -lapr-1 -laprutil-1 time_cookie.o -o
And the FOREACH loop in it should use
curr_bucket = APR_BRIGADE_FIRST(bb);
while (curr_bucket != APR_BRIGADE_SENTINEL(bb)) {
curr_bucket = APR_BUCKET_NEXT(curr_bucket);
Anyway I wonder if anyone has done a Mysql/Json apache module.

Posted by Alan Knowles in PHP | Add / View Comments()

15 Nov 2006

davfs2, missing blog posts, digitalmars d, leds php support improvements

I posted a couple of blog posts last week that did not get syndicated well via rss. Mostly due to not modifing the publishing date when i posted them, so if you missed them and they sound interesting heres the links

PHP Grammer added to leds, and how to build leds
Note: is currently down (14nov2006 -server upgrade in progress.), so the compd patches have not been commited
Note: I've recently added quite a bit more php autocomletion, variable type guesing and inline help (displaying method docblock info when you autocomplete a method call) - again, this is waiting for to comeback

Multilanguage setup for Flexy and FlexyFramework.
Details how to set up multilanguage sites using these two packages (and Translation2)

Digitalmars D mailing lists

D does not have nice mailing lists like PHP, they have a news server, and web based forums. Since I like my Inbox overflowing with news, here's a little hack to retrieve the news, and post it to yourself... - great reading if you are interested in compiler design or just want to pick up D by listening.

Interestingly there was a post this week by someone deciding to use D rather than PHP for a project. This is something that I have been tending towards, although as the example above shows, PHP still has many advantages, with projects like PEAR making tasks very simple as the libraries are easy to use, readily available. But as time goes by, that situation for D is obviously improving. Oddly enough I can see a day (although not within 6-9 months) when writing a website in D would be preferable to PHP. (ohh the blasphamy)


Yesterday I continued looking at davfs2 , as this old post subversion and davfs described. i depend on my subversion servers being mounted using davfs2. and since reinstalling debian on my new desktop, i noticed that davfs2 was packaged and available.

The new maintained davfs2, has a number of significant improvements, like fusefs support (allowing more than 5 davfs2 mounts), secret file (for password storage ) and caching. Unfortunately the last of these makes the new davfs2 unusable for svn mounted writable repos.

There are two dealbreaker bugs, which may be related. The first is caused by the fact that when you save a file, it writes the file locally first, then sends the file to the server in the background. This leads to a problem, that the true file mtime can not be correctly determined. (as the file has not actually been written to the subversion server when you saved it.) Leading to text editors thinking that the file has been modified on the server shortly after saving.

The second problem, intermittent write failue, appears to be fixed by the patch i posted to the davfs2 bug tracker, but does it by breaking the davfs internal logic .

So after spending far too long trying to fix it, i gave up and reverted back to v0.2, which works reliaby ,albeit slower.
Posted by Alan Knowles in PHP | Add / View Comments()

21 Aug 2006

Code Reviewing.

[** not proof read yet ;) - so send corrections not complaints ;) **]
As my freelancing work has scaled up into a full on company (of one still). I have had to evolve from being a one-man coding band into a team leader/manager. This introduced, over the last few years, a slightly different way of working.

Phase I

Specification writing, normally involving doing Inkscape interface designs, along with a huge gnumeric code specification, detailing the database design, along with explaining all classes and templates need for a project.

Phase II

Outsourcing, either to third parties, or to team members within the office I work with. Including a roughly 50% complete code review.

Phase III

The oh sh*t, it's getting urgent, we better fix the delivered code and make it work well enough for the client to start testing.

Phase IV

The what seems like never ending bug finding and fixing stage.

Where I am at present.

Two of the larger projects I have at present are in Phase II & III. One is being forced to go live, the other is halfway through development. Both being coded by different teams, however, what is interesting is that the issues that come up in the code reviews both, have been pretty similar.

The specification stage, perhaps the most labourious, and sometimes mind numbing if it gets large, is always interesting to look back at. The more I do it, in hindsight, It tends to make you realize, there is no such thing as a perfect specification. It always ends up as a best guess, based on what you think is needed and what you think the end user probably wants.

Dealing with end users is always fun, thankfully, this process tends to deal with the end user in two seperate phases - The Specification and the Bug fixing. (Although what normally happens is that after the bug fixing there is another process called changes - which gets dealt with almost as a new project)

What has interested me alot in the last few weeks, has been, to see how far some parts of the specification I wrote and designed, had to be dramatically changed During Phase III. It seems that however much thought and consideration went into the concepts, there is no way to totally predict how the look and feel translates to trying to actually get things done using the application. I've spent alot of time doing mass culling of parts that I spend considerable time trying to specify down to some detail, as when I sat down to test it, It was completely confusting.

Anyway, what I really want to go into, is some of the interesting code that comes out of the code review. Both half way through the project, and the complete overhall that has to be done as you push a project live. So you can demand payment (or at least beg for it..)

Coding Standards

Thankfully, I have managed to cobble together a quite large project coding standard to try and keep projects on track. Without them, Stages III and IV would become unmanagable, as tracing exactly how code was implemented so that both changes and refactoring would become completly impossible.

Unfortunatly, however clear the standards are (or you thought they are), developers have a nack of not following them, either out of habit or just the pressure to deliver so they can get paid.. - So a certian part of the halfway Phase II code review ends up just reiterating where they have missed those elements.

Common mistakes include
  • Not following the 'no if without braces rule'
  • not cloning DataObjects, as we develop in both PHP4 and test in PHP5
  • creating javascript libraries with functions in them.
  • creating PHP includes with functions in them
  • Not making the most of the automated url rewriting that FlexyFramework and HTML_Template_Flexy do for CSS, javascript and images.
  • Using mysql_real_escape, rather than the more portable DataObjects' escape() method. (which really wraps PEAR DB/MDB2)
  • Incorrect Indentation in javascript files.
  • passing strings around as error messages notices, rather than using error and notice flags, so the text of the message is on the templates, rather than in the PHP code.
  • Implementing magic constructors on the base controller...
  • using $do->whereAdd('somevar=1') when $do->somevar = 1 will do..
  • adding ?> at the end of the file ;) - It's not needed, and will come back to bite you one day.
  • Hard coding email subjects etc. in the PHP code, rather than using email templates.
  • Adding too many config options - especially file locations.
Reviewing the code also is a great opportunity to update and rewrite some of the standards so that things like this should not happen any more. (Although I wonder if making it bigger means there is even less chance they will follow it)
  • using 'print' rather than 'echo'
  • for xmlHttpRequest called code, using 'exit' in the get()/post() methods, rather than trying to get clever with content-type, and modifying the output method.
  • don't do the page processing in the output method()
  • stopping the use of javascript shortcuts - ie:
    • function ID(n) { return document.getElementById(n); }
  • using libraries that where not specified.. or using non-PEAR libraries when PEAR ones are available... - or creating libraries and plonking them in the Application Tree, with the wrong file/class mapping.
  • using commandset/command in XUL rathar than simply oncommand and the Javascript call.
  • using cwd(), rather than using dirname(__FILE__), for determinig the path for reading data files.
  • creating new object/array's when cloning dataobjects will work.
  • working with session variables from classes outside the one you are in (in The Framework, classes own a session variable $_SESSION[__CLASS__]..., and other classes should not access it directly).
  • not implementing a 404 return for unknown get's on the main page.
  • passing get/post requests back up to the main page using parent::get()...
  • Hard coding options (eg. enums) into controller classes (eg. currencies or statuses etc.) - put them in the DataObjects, so other pages can get the same list.
  • Overlaying config var's into the controller as raw properties..
  • Doing PHP calls in the template that involve alot of Database calls (that are critical and could fail) - Which is why we design code to do the processing before any output occurs, so we can redirect and handle issues gracefully.
  • Trying to get clever with sessions to pass errors about, when internal redirectors are intended to send notices back to the next page. (eg. HTML_FlexyFramework::run('',array('notice'=>array('user_updated_ok'=>true)));
  • excessive nesting of if/while/if/...else etc. - kill that nesting, return, continue or exit from conditions early, eg. negative test, and return, rather than positive test, and if/else.. nested many levels.
  • Consistantancy withdataobject methods, in general, dont do updates to a dataobject on a call, unless the method hints' that it might do it... -> eg. $do->approve() or $do->approveAndUpdate(); ...
  • Avoid silly code... $obj->is_verified = Project::isAuth() ? 0 : 1 .. either just cast it (int) , or let DataObjects worry about it...
  • Making lines so long you can't read them... Creating an instance of an object to call a method that 'could' be static, is not a bad thing, MyProject_DataObjects_Sometable::callaMethod() or $x= DB_DataObject::factory('Sometable'); $x->callaMethod();
  • Expecting me to chmod directories hidden away in the application. If you need to create temporary or semi temporary files, use the Template engines's temp directory, rather than trying to create them in the Code source somewhere (so that changing file permissions on svn up/checkout is not needed) - We can always change our default temp directory with set ini_set(session.save_path) in the bootstrapper..
  • ConfigData/default.ini are generally depreciated in favour of using the bootstrap to define the default options - and we have a slightly different bootstrap defined for our servers.
  • Assuming it's ok to delete stuff! instead, it should be a basic assumtion, that nothing get's deleted from databases (eg. it always get's flagged), so dont write code that actually deletes it, and always check the deleting flag when searching...
  • Forgetting to extend the Project base class - Everything extends the base class, even code run via cron jobs.

And sometimes, you realize that the rules you set down may not be totally the best idea...
In one case I advocated using $do->setFrom() rather than seeing a big list of map's between $POST[] / or something else and a dataobject. However, in some cases either building the object slowly and clearly or listing what you send to setFrom() makes the code considerably clearer.

In more detail

In the extended entry I'll look a bit closer at some of these deviations from the ideal..
Posted by Alan Knowles in PHP | Add / View Comments()

28 Jul 2006

Getting Started with HTML_FlexyFramework, DataObjects and HTML_Template_Flexy

Since most of the applications I write, and get teams to write for me, use the FlexyFramework, I though some simple instructions might be usefull.

FlexyFramework, is an extremely simple pair of classes that help load action classes, do internal redirection, and load up basic configuration settings. Basically taking all the hard work out of setting up a reasonably secure web application.

In this simple example, I'm going to use a little project called FlexyCash, so if you are setting up a project, just replace all the references to FlexyCash with your project name.

You'll have to visit the site, as the actual tutorial is in the extended entry bit....

Posted by Alan Knowles in PHP | Add / View Comments()
« prev page    (Page 2 of 7, totalling 63 entries)    next page »

Follow us on