WordPress hacked…

The past three weeks my WordPress blog got hacked two times. As a regular visitor nothing seemed out of the ordinary, but if you searched Google my blog seemed as a the best drugstore in town (Generic cialis – We Always Have The Cheapest Offers In Our Online-Drugstore). Each and everyone of my blog-pages had corrupted html-title tags or title-id’s (only when viewed through search engines!). Thanks to Google Alerts I found out there was something strange going on.

After a lot of searching (nothing mentioned on the web), finally found the problem. Seemed like my WordPress plugins got edited without my knowledge into base64_encoded hidden code which was then parsed with the php eval() function.

This is what it looks like…

@eval(base64_decode("JGFjdD0iaW1nIjsgZ2xvYmFsICRhcnJfdG...")); ?>

I found different entries in the following plugins: wp-spamfree / rss-import / syntaxhighlighter and so on. I changed all passwords to my site (webspace and databases) and deleted the infected files. Many of those files had changed permissions! I found unknown references to *.bak.php files inside the wp_options database table autoloading various scripts.

Fingers crossed that this won’t happen again. I will keep my eyes on Google / Bing and other search engines to see if my site keeps attracting unwanted visitors.

Google Labs was the only place giving me on the fly information of my cleanup-progress. Unfortunately Google Labs has a request limit on a week to week basis. I haven’t found a similar functionality in BING. So if you reach the request limit, you’re out for the next 7 days…

To give your wordpress some additional security you can password protect the wp-admin directory with .htaccess and .passwd.

If your WordPress gets hacked too, leave me a message if you encounter similar problems. I still don’t know how these files got changed in the first place.

Enter Songbird, Exit iTunes of eerder WinAmp of MediaMonkey?

Songbird logo

Het ging niet lang meer duren, zo bleek al uit een van mijn vorige berichten. Ik heb iTunes nu definitief naar de prullenbak verwezen en Songbird geïnstalleerd. Wat een verademing, of toch niet helemaal?? Continue reading “Enter Songbird, Exit iTunes of eerder WinAmp of MediaMonkey?”

Posting HTML forms with special characters, while keeping your database clean.

The best practice when storing data in a database is to store it in its most purest form.
When allowing users to edit data through HTML webpages you need to encode some characters so your HTML-forms won’t break. You can do this by using htmlspecialchars (or htmlentities). Below is an example with htmlspecialchars where only the double quotes are escaped (ENT_COMPAT flag).

Mind the accept-charset in the form value: I try to work with UTF-8 and UTF-8 only. (see your collation in mySQL is also set to UTF-8!)

You can run this on code on localhost (e.g. XAMPP)

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>htmlspecialchars (utf-8 encoding)</title>
<h1>htmlspecialchars (utf-8 encoding)</h1>
<h2>Before form post</h2>
$dbvalue = "String: ? < > ' - \" `´& % ‰ € ® 2011";
$formvalue = htmlspecialchars($dbvalue, ENT_COMPAT,"UTF-8");
<p><strong>String</strong> is a value coming from a database record in its cleanest form: <span style="color:green;"><?php echo htmlspecialchars($dbvalue); ?></span> </p>
<p>For use in a text form, especially the double quotes, must be encoded so the <em>value=&quot;&quot;</em> doesn't break. We use <strong>htmlspecialchars</strong> (ENT_COMPAT) function. ENT COMPAT only forces double quotes to be changed into &amp;quot; (besides < > ? &)</p>
<form action="<?php $_SERVER['PHP_SELF']; ?>" method="post" accept-charset="UTF-8">
	<input name="string" type="text" value="<?php echo $formvalue; ?>" size="50" /></label>
	<br />
	The value of title inside this form looks like <span style="color:red;"><?php echo htmlspecialchars($formvalue); ?></span><br />
	<input name="submit" type="submit" value="submit this form" />
<?php if($_POST){ ?>
<h2>Yes, the form was posted</h2>
<p>When the form is <strong>submitted</strong>, the <strong>string</strong> field will again have a value in its purest form (no &amp;quot; values but &quot;) (not the htmlspecialchars formatting)</p>
<p><strong>String</strong> has submitted value: <span style="color:green;">
	<?php echo $_POST['string']; ?>
<?php } ?>

Foreign Key Constraints en Display fields in phpMyAdmin

Een van de handigheden in phpMyAdmin is dat je bij een aantal storage engines zoals innoDB  en myISAM een ‘display field’ kan instellen.

Het display field is eigen aan phpMyAdmin en heeft niets met mySQL te maken. Wanneer je een display field aanmaakt via phpMyAdmin zal zich dat niet vertaald zien in bvb mySQL Workbench.

Bij INNODB kan dit ook nog een extra aanvulling zijn op  foreign keys .

Bij het invoegen van een record wordt automatisch een drop down lijst gegeven van de mogelijke opties wanneer een relatie gelegd is naar een andere tabel. Indien een foreign key constraint bestaat voor een bepaald veld wordt niet alleen een ID getoond naar de verwijzende tabel, maar ook een omschrijving (display field) van de verwijzende tabel. Dit biedt het voordeel dat je niet eerst de verwijzende tabel moet openen en daar gaan zoeken naar de juiste ID.

Laten we uitgaan van het voorbeeld dat je ook op Wikipedia kan terugvinden. Een tabel waarin je de namen van je klanten bewaart en een tabel waarin de bestellingen van alle klanten opgesomd zijn. Elke bestelling wordt geplaatst door een bepaalde klant. In de bestellingentabel definiëren we dus een foreign key naar de tabel klanten.

Tabel 1: klanten


Tabel 2: bestellingen

klant (foreign key naar klanten.id)

Het ‘display field’ instellen gebeurt in de ‘relation view’ van de verwijzende tabel (namelijk klanten). Deze relation view is toegankelijk in het structuur menu van de tabel. Als display field kies je in dit geval dus ‘naam’.

Wanneer je nu bestellingen gaat invoeren via phpMyAdmin krijg je bij het invulveld klant een dropdown lijst te zien met de namen (en bijhorende id) uit de klantentabel. Het voordeel is dus dat je niet in een apart venster eerst de id moet gaan opzoeken die bij een bepaalde naam hoort.

Als je meer dan 200 klanten hebt, zal er geen dropdown meer verschijnen, maar een zoekvenster. (zie pmaWiki)

Er is wel een nadeel verbonden aan ‘display fields’. Ze worden namelijk niet geëxporteerd bij het nemen van backup van de database. Dit komt omdat de ‘display field’ een functie is van phpMyAdmin zelf, en niet van MySQL.

Null waarde als (deel van) primary key in MYSQL

Lijkt evident, maar is het niet: als je een samengestelde ‘primary key’ definieert in mySQL waarbij een van de delen van de primary key NULL-waarden kan bevatten en identieke rijen wil uitsluiten, kom je bedrogen uit.

Neem bijvooorbeeld volgende tabel waarbij je twee identieke rijen wil uitsluiten met behulp van de samengestelde primary key ‘user, e-mail, label’:

user email label
1 test@test.be 2
2 test2@test.be NULL
2 test2@test.be NULL

Rij 2 en 3 zijn voor jou als gebruiker identiek op het eerste zicht en zouden elkaar dus logisch uitsluiten. De database zou de derde rij niet mogen toelaten indien een samengestelde primary key is opgesteld over ‘user, email en label’, maar aangezien voor MySQL NULL waarden nooit identiek zijn, is dergelijk situatie perfect mogelijk in MySQL en moet je dus op zoek gaan naar een andere oplossing!

XHTML: some good practices

Some good practices on XHTML

  • <doctype> always use a doctype before <html>-tag: don’t get in quirksmode –recommended list of doctypes (W3 schools)
    • Transitional is most common
    • Strict: prohibits the use of target=”_blank” and a few other HTML tags, like s, center, strike, u, applet, iframe, font, isindex, dir, basefont
  • <h1> Only one h1 per page: use for the main topic
  • <blockquote> Only to refer to bits of text coming from other locations
  • <q> Use for a single ‘quote’
  • <table> Never use for lay-out purposes
  • <cite> References to books, websites, articles
  • <address> identify contact information to the author of a page

Other usefull tips

Disallow compatibility mode

Tell Internet Explorer never to go into compatibilty mode (use an older IE engine than the one installed). Put this after the <title>-tag:

Linking style sheets

Use <link> for simplicity and better performance

Validate your code


Forget about HTML attributes like

  • vspace
  • hspace
  • bgcolor
  • text
  • link
  • alink
  • vlink
  • img align: use CSS-floats instead

Low level format browser specific attributes like

  • leftmargin
  • topmargin
  • marginwidth
  • marginheight