Archive for March, 2008
I've upgraded WordPress and I'm working on putting things back to normal.
In the process, I've discovered a few more side effects of the hack. It appears that the hacker uploaded a new header.php and footer.php to my active theme. I only noticed this because I had changed the theme and placed some important markup in the header. Without this markup, the page doesn't render correctly. If you are viewing this site on the evening of the 27th, you might just well be seeing the old theme while I work on fixing the new one.
The footer was modified to include hidden links to various link farm pages on a health and fitness podcast. The header was modified to include only one link, this to a blog run by someone by the name of Erik Kastner. I won't give you the links because ... well ... that's the point.
I've posted a comments on these blogs asking for help in figuring out this connection. I'll let you know the response.
Please see Erik's reply in the comments. My current working theory is that the hidden links in the footer -- obviously placed to improve SEO, not to gather direct links -- are the main payload of this attack. I suspect that the hidden link (Erik's link) in the header points to the next site that the attacker plans to compromise. This forwards the page rank and makes the payload on the next page more valuable. Erik's blog runs on WordPress as well, but his was patched.
So thanks, Erik. Let's hope that I get a quick response from the health and fitness podcast.
It happened again. The db_version was reset to 1 this morning, causing the error message "Your database is out-of-date".
My forensic analysis turned up nothing. Whatever caused this also had the effect of disabling the Spam Karma plugin, so all of the comments posted thereafter were sitting in moderation. This gave me a good timestamp for the occurrence.
Since the version change disables the spam filter, I suspected an attack. Perhaps someone takes advantage of a WordPress bug to turn off the filter and then post a bunch of comment spam. So I checked the server log for any suspicious entries around the time of the earliest comment in moderation.
The earliest comment was at 22:56 GMT. My server is located in the -400 time zone, so I scanned the access log for 18:56. I can see a "POST /blog/wp-comments-post.php" at that time, so that is the first comment post with the spam filter turned off. Scrolling back to the previous post at 18:43, I have my window. The version change and disabling of Spam Karma occurred somewhere in there.
At 18:45, there are several POSTs to various suspicious URLs.
Unfortunately, I cannot see the body of the HTTP POST from the access log, so I don't know exactly what was done. But it appears that someone used these entry points to change some options and upload a file called "ro8kfbsmag.txt". Googling this filename, I found that it is indeed an attack.
It looks like this vulnerability has been fixed. So the solution is to upgrade to the latest version of WordPress. I know what I'll be doing tonight!
Phentermine No Prescription
Information credit report
Highest credit score
Shell credit card application
Online Cialis Jelly
Information credit report
Repair credit score
Credit reports com
Chase redit card srevices
3 credit report
Credit score ranges
Disputing credit reports
Counseling credit card debt
Commercial credit report
Debt consolidation credit cards
Online Herbal Phentermine
Free Mp Ringtones
Check credit report
Credit score system
Cheap Viagra Jelly
Credit score in
Credit card offer
Cleaning up credit report
Free credit report scores
Credit report monitoring service
Credit card deal maker
Cialis Soft Tabs
Cheap Viagra Soft Tabs
For some reason, WordPress started throwing the error "Your database is out-of-date. Please upgrade." whenever I visited the admin console. I had not upgraded either the code or the database prior to getting this error. I have no clue what caused it.
So naturally, I Googled the error message and found many other people with the same problem. Some of these people received replies to their cries for help. The replies included such helpful tidbits as "so upgrade, already", to "reboot the server". Naturally, I tried them and none worked for me.
Since WordPress is written in PHP, the source code is entirely in the clear. This makes it possible for a typical software blogger like myself to debug the application and figure out what's wrong. I used PuTTY to log into my server and peruse the code and database to see what could be done. I thought this would make for gripping television, so I did it all while streaming.
Here's my solution
I found that a single value in the wp_options table had been changed. It should be 4772, but it was 1.
If you grep for the error message, you will find a comparison between get_option('db_version') and $wp_db_version. Further grepping will reveal that $wp_db_version is set in wp-includes/version.php and that get_option selects option_value from the wp_options table. Log into mysql and select * from wp_options where option_name='db_version' and you will find the culprit.
This solution is not for the weak of heart. If you are not familiar with mysql, please take some time to get comfortable with it before messing around with your own blog. You run the risk of seriously messing things up, especially if you forget your where clause!
If you are not familiar with PHP, however, not to worry. This fix does not require any changes to the WordPress PHP code. In fact, this exercise is a great way to learn.
So if you found this post by Googling your error message, watch the video clip, get your PuTTY ready, and fix it!
BTW, how did the value get changed? Not a clue. If it happens again, I'll investigate further. And I'll stream the process!
I have released Update Controls .NET as an open source project.
Update Controls is a set of .NET Windows Forms controls that update themselves automatically. Instead of setting properties, you handle events. For example, the GetText event fires on an UpdateTextBox when it needs to update itself. The event returns the text string to display. Then, when any data that was used to calculate that string changes, the event fires again. Automatically.
Think of how you use a spreadsheet. You enter a formula in a cell, with references to other cells. When those other cells change, the formula is recalculated. You don't have to tell it to update, it just figures out when to do so.
I created the algorithm at the core of Update Controls almost ten years ago in C++. Since then, I've translated it first into Delphi, then Java, and finally C#. The Update Controls library is that core algorithm applied to the common Windows Forms controls. It also includes a handful of themed controls for better visual appeal.
Not data binding
For as long as Microsoft has done demos of VB, they've tried to convince us that we can write real software with zero lines of code. It works fine on the projector screen, but it fails to translate to a full-scale application. Once you get outside the box of direct column/control relationships, it is impossible to adapt data binding to your needs.
But Update Controls is completely flexible. You can start with a simple event that returns one value, but then modify it to combine two or more values as your needs change. Since you are writing real code, you are in complete control.
A data-bound control attaches directly to a column in the database, or a property of an object in the data model. It cannot call through more complex business logic.
But an Update Control can call any business logic that you specify. Whatever data the business logic touches in order to do its work, that data affects the control's behavior. When any of it changes, the event fires and calls the business logic again.
Not the observer pattern
The observer pattern is obsolete. It requires that you manually register each observer with each subject. To make it work, you have to know ahead of time all of the objects in the data model that affect each user interface component. A large portion of your source code is dedicated to making and breaking those connections.
Update Controls, on the other hand, discovers those dependencies on its own. It can see through business logic, so you don't have to directly tie your user interface to your data model. And if that business logic switches to a new path, the dependencies are updated as well.
The observer pattern also suffers from cascading redundant updates. If your observer depends upon two subjects and both are changed at the same time, the observer pattern will give you two updates. The problem gets even worse when you have indirect dependencies, as the redundancy rolls through the system like so many dominoes.
But Update Controls queues the updates until the last possible moment, so they occur only once. Even indirect dependencies are calculated in the best possible order, with each update being invoked just once as the information bubbles to the surface.
Please give it a try
The library works in C# and VB. It can be used in either Visual Studio 2005 or 2008, with .NET 2.0, 3.0, or 3.5. You can download the source code and build it yourself, or just run the convenient installer. Videos, demos, and documentation are all available to help you get started.
Once you write a Winforms app with Update Controls, you'll never want to code without them.
I'm starting an open source project (details on which later this week). Part of the process is selecting a license.
This is a library, so the intent is for it to be used by and within another application. In fact, this library is well suited to use by other libraries. As such, I didn't want a viral license like GPL that would prevent some legitimate business uses of my code.
A non-viral GPL
The GPL has come under scrutiny for separating the world into free software and not-free software. Free refers to the freedom of use rather than price; it is possible to charge for free software. But regardless of business model, the GPL doesn't allow these two camps to meet.
To answer this concern, in 1991 the Free Software Foundation created the LGPL. Originally the "Library GPL", it was intended for reusable code. An application could link to the code without being infected by the GPL.
The FSF revised the LGPL in 1999, changing its name to the "Lesser GPL". They also released the article "Why you shouldn't use the Lesser GPL for your next library".
The article reads very much like a call to arms. It says that they are seeking more libraries to release under the original GPL. "[F]ree software developers need to make advantages for each other". This article, and the somewhat derogatory name change, make it clear that they would prefer that we don't use the LGPL.
Nevertheless, the license does exactly what I need it to do. It grants licensees the right to copy, modify, and redistribute my code. It also grants them the right to license any derivative works however they see fit. Even though I am not a card-carrying member of the open source movement, I believe that this is the best model for this particular library.
I'm back from the joint application design sessions, and happy with the progress we made. But one discussion stands out as having taken longer than it should have.
We got to the point of deciding how our systems would physically talk to each other. They have some data to send to us, and we have some data for them. The usual requirements apply: the data has to be validated, the channel has to be secure, the transport has to be reliable, and the process has to be auditable. Still it took an hour to work through the details.
What we agreed upon was delivering XML files over SFTP. Standard features apply: one folder for incoming and one for outgoing, acknowledgement files, XML schema for validation, and exception reports emailed to a distribution list. In particular, we spent several minutes talking about what to do on days on which no data is exchanged. Do we send an empty file or no file at all?
This seems familiar
This problem has been solved before. In fact, this exact solution has been done before. There is nothing new here. Even so, this lengthy conversation among seasoned professionals had the air of invention. There were several problems raised, multiple solutions proposed, and many points argued. But in the end, what we "invented" together is a well-known pattern.
I don't mind that the solution we agreed upon uses older technology. Sure, web services or REST would have been more in vogue. But even with these newer standards, you have to agree upon a pattern of use. What was so frustrating is that this is a pattern, and yet the group spent an hour rediscovering it.
If you install any ESB solution, it will include components out-of-the-box that implement this pattern. You just configure them with a polling frequency, a transport protocol, a schema, and an email address. No code required.
The value of patterns is that you can work at a higher level of abstraction. All the details have been solved for you in advance. This saves time and improves communication.
And, BTW, the correct answer is to send an empty file. We finally agreed upon that, and congratulated ourselves for our brilliance.
Despite all expectations, today was incredibly productive.
I've been meeting with the other partners in this large integration project to try to reach some consensus. The grand-client has scheduled these "joint application design sessions". Sounds suspiciously like design-by-committee.
Off to a bad start
I flew into town yesterday thinking that we were not far enough along in the project to have anything useful to share with each other. We're supposed to be jointly designing this application, but we haven't even nailed down the business requirements.
Because of a delayed flight, I missed yesterday's session and ended up in a project planning meeting (see yesterday's post). I heard from others present that there was not much content that pertained to us. Then I heard from the PM that we would be "observers" in the sessions for the next two days. That did not set the stage well.
Nevertheless, I decided to go in and make the most of it. Being the BA, I had with me a nice long list of open issues. I'm keeping these issues in an Access database tagged by functional area so I could quickly query for the questions I needed to ask at each point. Since the business requirements are not yet complete, most of these were business questions.
It turned out that we were better prepared than I thought. The other partners were similarly prepared, and everyone had business questions to get resolved. These are issues that have been open for months. We could not reach consensus with email or conference calls. But get everyone in a room, uncomfortable, with a limited amount of time, and things got done.
After closing many of my open issues, and assigning a few more to various people as action items, we were able to settle into more technical discussions. We agreed upon a high-level data interchange design and required data elements, with XML schemas to be provided within a week.
We were not mere observers. We had answers that they needed, and they had answers that we needed. And this was not design-by-committee. Instead of a lukewarm mixture of everybody's ideas, we each identified our own unique place in the system.
So don't underestimate the value of getting partners together. In just a few hours, you can accomplish what months worth of emails just can't get done. And even though design-by-committee yields mediocre results, integration of system requires some integration of teams.
I'm traveling again, but this time not for fun like the ODC. This is work. I'm traveling to represent one of SSG's clients to one of their clients. The "grand-client", if you will. SSG has asked that I don't blog company names, but you'd know them if I told you.
A tale of two cultures
The grand-client has a very comprehensive software development lifecycle. It grew out of their Y2K effort. The process is heavy, but it helps them to mitigate risk.
My client, on the other hand, has been trying to define their process. Traditionally, they use RUP, but have had issues in the past with generating useful documentation from this process. They've evaluated agile, but could not get it to work within their corporate culture. Most recently, they've described their process as "agile RUP". I'm sure that such a combination could be achieved, but this seems more like a compromise than an actual plan.
This is a large integration project. The grand-client has identified several partners that will work together to create a new product offering, my client being just one of them.
The grand-client is running this project by tracking each of the partners with their own methodology. Instead of expecting deliverables from each provider at certain milestones, they are integrating the project plans.
Project management tooling
The project management tools couldn't be more different. The grand-client uses a centralized task management system. Engineers enter time against these tasks, and the tool compares those against the plan to automatically update the schedule.
On the other hand, my client manages everything with Microsoft Project. Engineers enter time against milestones, not tasks. The project is manually updated at status meetings, not automatically based on the time entry system.
The goal from the grand-client's point of view is to create a synergy of processes. They want to map all of the artifacts in the client's process into their own process. With that mapping, they can measure all partner's progress with their own tool, and identify each one's impact on other partner's schedules.
This might be a brilliant way of managing a project of this scale. Or it might be a train-wreck in progress. Either way, I expect to learn quite a bit from this engagement.
There's a long post by Jeff Moser entitled What Does It Take To Become A Grandmaster Developer? The post itself is interesting, but I'd like to call out one thing that I immediately reacted to.
A foolish [assumption] would be to believe that you could exclusively live at the higher levels without understanding the lower levels. [...] Early on, I thought it was always possible to "raise the level of abstraction." I was wrong.
I am all about raising the level of abstraction, so I thought he was calling me foolish. He seems to be saying that we cannot escape the details, even as we find the chunks that make them easier to remember.
After calming down a bit, I realized that he was saying something much more intelligent. He's saying that it is not always possible to completely hide details behind an abstraction. Further, he's implying that it is not always desirable to do so.
Two kinds of abstractions
The reasonable viewpoint that I missed at first is that there are two kinds of abstractions. There is the "leaky" abstraction that lets the underlying detail show through. Then there is the complete abstraction that hides those details from you for your own good. Both of these abstractions are useful.
Examples of leaky abstractions are web application languages like JSP and ASP. These generate HTML for you. They are an abstraction over HTML that relates it to your application data model. But they do not completely hide HTML from you. In fact, both of these languages live inside what looks like an HTML file.
Examples of complete abstractions are languages like C. It completely hides the underlying machine code. For an exceedingly large class of problems, you never have to write, look at, or think about machine code. At one point in history a knowledge of machine code was useful to C programming. But in this day, it's hard to argue that someone needs to have felt that pain in order to be a good C programmer.
Because JSP and ASP are leaky abstractions, they can never be decoupled from HTML. But because C is a compete abstraction, it can be ported (with varying degrees of success) to other platforms.
An exceedingly large class of problems
An abstraction is a model of the underlying idea. C programming isn't machine programming, but it represents machine programming. It captures the essential features required for a certain class of problems. Sure, there are problems outside of this class for which you have to write machine code. Boot loaders, operating systems, and device drivers can probably not be written entirely in C. But these are the minority. An exceedingly large class of programs can be written in C.
To make a complete abstraction, you must first identify the class of problems that you intend to solve. All problems in this class can be solved using only the features of the abstraction. Problems outside this class will require features of the underlying idea.
Necessary and sufficient
Once you have defined a class of problems, you can apply the concepts of necessary and sufficient features to create a complete abstraction for that class. Go back and read previous posts from the dof (Degrees of Freedom) category. This post appears in that category, so skip back.
Each of the features of the abstraction is necessary for solving at least one problem in the class. The sum of the features is sufficient for solving all problems in the class.
This is also known as the Goldilocks principle. The abstraction is neither too big, nor too small. It's just right for the class of problems it solves.
This is also known as composability and orthogonality. Each feature of the abstraction is orthogonal to the others because there is no combination of other features that can achieve the same effect. And the set of features can be composed to create a solution to any problem in the class.
Benefits of a complete abstraction
When you have a complete abstraction of necessary and sufficient features, you can solve any problem in a defined class. As long as you know that your problem belongs to that class, you never have to peel back the cover of the abstraction.
Not all abstractions demand this level of scrutiny and design, but those that do are often the most useful. They hide the details of the underlying idea for your own good. You never have to think about those details again. People new to the idea can focus on the abstraction and never even learn those details. And, those details can change without affecting artifacts created on top of the abstraction.