HTML5 already works somewhat

HTML5 is no radical departure from it’s predecessors. It offers aids to better semantic markup and embedded content, useful form validation, and a little less depreciated cruft. Most importantly it provides the platform for CSS3, about which more in a later article. But the best thing about html5 is that you can have it now, without sacrificing browser compatibility. Take a look over here where I’ve recoded Ponderwell’s site in html5. That was an afternoon’s work, and the result was sufficiently encouraging that I think I’ll be using html5 exclusively from now on. It works just fine even in IE6 – or rather, it works as well as any site ever does in that horrible browser.

(more…)

Until Firefox gets full css3 word-wrap: break-word support…

Ok, so you have a beautiful layout.  You are letting users insert data (properly validated, of course), and someone posts a raw URL or other text without a space in it.   Your layout is, well, borked.   You could of course:

  • wrap  the text in a div and apply an overflow-x:auto and give it an ugly scrollbar
  • wrap the text in a div and apply an overflow:hidden, hiding their content, but not disturbing your layout.
  • Deal with it until the CSS3 standard is totally accepted in all browsers used by all clients ( word-wrap: break-word ).  IE already understands this syntax.
  • This technique, inserting <wbr> tags inside the text telling the browser to break mid-word.

Some background information, the <wbr> tab is a little-known html tag that means  “The browser may insert a line break here, if necessary.”  It’s supported by Firefox, which is important, because IE and Safari support the word-wrap: breakword CSS3 attribute.  Getting your content to contain <wbr> tags when the text is quite long require either server side code, or client-side javascript.  I’ll go into how to do this with client side javascript.

One big caveat about <wbr>, while it still works, it’s considered deprecated.  Your pages may not validate.

Here is a function that accepts an incoming string and begins looping the string.  Every 7 characters, it’s adds a <wbr> tag, unless it finds a space character.  It starts counting again if it finds a space character, as the browsers will naturally break here.

[javascript]
function wordwrapper(text){
var counter = 0;
var thisChar;
var out =”;
for(var i=0; i &lt; text.length; i++){
counter++;
thisChar = text.charAt(i);
if (thisChar == ‘ ‘){
counter = 0;
}
if (((counter % 7) == 0) && (counter != 0)){
out = out + thisChar + ”;
}
else {
out = out + thisChar;
}
}
return out;
}
[/javascript]

I still suggest using this in conjunction with the style word-wrap: break-word, as that’s more reliable to fully css3 compatible browsers (and IE, which miraculously already supports this!)

The code’s one gotcha (that I know about) is that it may put a <wbr> directly before a space character, where it isn’t needed. If any reader has a code snippet to share that will only insert <wbr>’s in the string if there are no whitespaces before or after the <wbr>, please share in the comment section.

Fruit harvesting using graudit

Fruit Harvesting using graudit: Find your bad fruit

graudit is a static analysis tool which is basically grep on crack. It is essentially a bash script which uses grep to find very low hanging fruit (issues) with your PERL, PHP, JSP, .Net, and Python source code. While this tool is a good first start, especially for developers with little secure coding knowledge, it does not take the place of a good audit application like O2 or Fortify 360 SCA.

Getting a feel for the tool

graudit is developed and maintained at http://www.justanotherhacker.com/projects/graudit by a very knowledgeable hacker (whos name I do not know and could not find on the website – sorry). The reason I think the developer is knowledgeable is due to the other blog posts on the website. Going by these articles, the developer has a vast knowledge of web application security and posts regularly with his/her thoughts. I highly recommend ingesting the RSS feed on your fav reader.

graudit is currently at v1.6 and v1.7 is supposed to be available soon as well. It is an OSS project and the developer has another project to test websites and clients to those websites as well.

After downloading and extracting the tarball, we are left with a directory structure like so…

drwxr-xr-x  3 mduncan mduncan  4096 2010-05-14 05:27 ./
drwxr-xr-x 80 mduncan users    4096 2010-06-02 12:53 ../
-rw-r–r–  1 mduncan mduncan  1463 2010-05-14 05:27 Changelog
-rwxr-xr-x  1 mduncan mduncan  2815 2010-05-14 05:27 graudit*
-rw-r–r–  1 mduncan mduncan 35148 2010-05-14 05:27 LICENSE
-rw-r–r–  1 mduncan mduncan  1951 2010-05-14 05:27 README
drwxr-xr-x  2 mduncan mduncan  4096 2010-05-14 05:27 signatures/

The primary executable is a bash script which loads disctionary-like signature (or database) files from the signatures directory. Currently, the tool has signature/database files for a number of languages including PERL, PHP, JSP, .Net and Python. More of these signatures can be developed by you — they are pretty simple — or passed to the developer for incorporation into the project.

Each signature file is basically sent to grep using the -f <pattern file> option and contains (on each line) some pattern to look for in files it will search. For example, in the PERL signature file, it will look for any read or open function calls.

Running the tool

To run graudit on a script, you simply run it like so…

<path to graudit install dir>/graudit <filename or directory to audit>

You can run the script on a directory containing sources for your application or simply a file. Either way, grep is used to scan the file(s) for key words listed in the signature. By default, it uses the all database, but you can hone your scans to a particular language/signature/database like so…

graudit -d <name of dictionary> <filename or directory to audit>

The option -d <name of dictionary> is just the dictionary/signature to use without the .db extension from the signatures directory.

Assessing the results

graudit is a great start to writing more secure applications. Unfortunately, because it uses only grep to find keywords, you are going to get a lot of false positives. For example, when scanning the following code (PERL)…

[perl]
use strict;
my $file = "myfile.txt";
my @contents = ();
die "Error: $!\n\n" unless(open(FILE, "<". $file));
@contents = <FILE>;
close(FILE);
[/perl]

…I get the following result(s) from graudit…

# ~/apps/graudit-1.6/graudit -d perl test.pl

test.pl-4-my @contents = ();
test.pl:5:die “Error: $!\n\n” unless(open(FILE, “<“. $file));
[email protected] = <FILE>;

What graudit is picking up on is the fact I am using the open function to open a file here. This in most instances would cause some alarm to auditors, but graudit does not pick up on all of the issues here. We are using strict, which is a good start, but we are not validating $myfile and we are not using taint checks.

Now, if I edit the test.pl script I created above, remove the use strict line and set the $myfile variable to $ARGV[0], then there should be some concern by the auditor here looking over the code. This is because we could be using possibly tainted and unvalidated arguments to open a file on the system. Of course, this does not mean much here because we are not outputting the file nor are we using the arguments except to test open the file, but generally ALL PERL scripts should use strict, use taint checks and ensure that all inputs are properly validated before use within the script. Unfortunately, graudit falls short here…not picking up on the real security issues…

[perl]
my $file = $ARGV[0];
my @contents = ();
die "Error: $!\n\n" unless(open(FILE, "<". $file));
@contents = <FILE>;
close(FILE);
[/perl]

# ~/apps/graudit-1.6/graudit -d perl test.pl

test.pl-3-my @contents = ();
test.pl:4:die “Error: $!\n\n” unless(open(FILE, “<“. $file));
[email protected] = <FILE>;

Conclusion

While graudit is a good start, this article should point out that it does lack the capabilities of a good auditor and tool like O2 and Fortify 360. These tools know to look at the flow of code as well as the keyword searches that graudit performs. Fortify, which I use regularly, will for example, notice the lack of validation on inputs. But, unfortunately, because O2 and Fortify have to parse the language first, PERL support is not there. So, graudit is a good start to looking for issues in PERL scripts, but you will need to understand good secure coding and application design before using the tool. Like all security analysis tools, the auditor is the key to performing accurate and complete scans/audits on applications. Only an auditor knowing the languages and other technologies used can audit application effectively even with the best tools available.

Adding Google Analytics to “WordPress AudioPlayer”

If you are using the WordPress AudioPlayer plugin on your site, you know that it’s a versatile flash player with many options. The missing option from my point of view is tracking the playing of the audio tracks themselves. I’ll show you how to add Google Analytics tracking to the player, so you can get an idea of which of your tracks are most popular.

This technique should work on any flash swf that has an external javascript controller. The same principles apply. It also works just fine with WordPress AudioPlayer’s standalone version that does not require WordPress on your site.

Your site must be using the new Google asynchronous tracking code, and it must be in your page header, not your page footer. If you don’t want to put the code in yourself, check out the WP plugin Google Analyticator. You can, of course, just paste the async code directly in your header if you want to be old-school about it. Remember to remove your old tracking code in your footer.

Once you have migrated your site to the new code (and it’s benefits), you’ll want to open your /wp-content/plugins/audioplayer/assets/audioplayer.js file. This is a little hard to read, as it’s been compressed to make pageload faster. You can see the whole file, in it’s uncompressed state on the AudioPlayer’s SVN server. We’ll be looking for the activate() function in the javascript, which is the function call that interacts with the swf when the player is, well, activated.

It looks like this in the uncompressed version:

[code lang=”js”]
activate: function (playerID, info) {
if (activePlayerID && activePlayerID != playerID) {
getPlayer(activePlayerID).close();
}
activePlayerID = playerID;
},
[/code]

And like this in the compressed version:

[code lang=”js”]
activate:function(I,J){if(D&&D!=I){B(D).close()}D=I},
[/code]

Before editing this code, you’ve got to decide on a URL structure you’ll be reporting to Google. I’m suggesting that you choose something that is unlike any other content on your site, so you can isolate your audioplayer plays. Choose a URL prefix that is unlike anything else in your site. For this example, we’ll report “/audioplayer/” as the base URL. Your URL should not be that of a real page on your site. We’re pushing “fake” pages to google to record our plays.

Now (after backing up audioplayer.js), edit the javascript file, and find the line for “activate”, and right after the D=I;, add our google page tracker:

[code lang=”js”]
activate:function(I,J){if(D&&D!=I){B(D).close()}D=I;
_gaq.push([‘_trackPageview’, ‘/audioplayer/’+ J[‘trackInfo’][‘artist’].replace(/\s/g,’_’) +’/’+ J[‘trackInfo’][‘title’].replace(/\s/g,’_’) ]);
},
[/code]

J is the javascript object holding information about the track, so by sending the J[‘trackInfo’][‘artist’] and J[‘trackInfo’][‘title’] as the page visited, we end up with URL’s in our google reports like /audioplayer/<artist_name>/<title>/

We are also replacing spaces in the the artist name and track name with underscores. The sites I run audioplayer on do not have multiple tracks per player, if you do have that on your site, you may find that what your are sending to Google is an array of title, which will appear as [object Object]. I’ll (perhaps) tackle that in a future article.

Troubleshooting: To see the data array, in Firefox, add this to your code right before the _gaq.push line:

[code lang=”js”]alert(J.toSource());[/code]

You’ll get a popup javascript alert that will show you the whole info array. (remember to take out the code when you are done looking!). This technique requires you to edit plugin files directly. You’ll have to patch your audioplayer every time you update it in WordPress. That’s a small price to pay for the extra functionality, and we hope that 1PixelOut extends their fantastic audioplayer to have these settings built right in the core in the future.

If you are interested in hiring us for javascript customization or other design / programming needs, send us a message

Newest Twitter w0rm details and how to protect yourself

Well, as you may have seen recently, Twitter has been hit again by a w0rm and this time it uses a Java-based exploit to run commands on a victims machine. Although this attack appears to target bank customers/employees and installs a key logger (an application to record all keystrokes made on the computer), it could-have/might-have-been-already changed to really run anything. You should know what to look for and how to protect yourself and/or your organization against such attacks.

What to look out for

The w0rm propagates by sending Tweets to Twitter users and they (currently) look like this caption from the  F-Secure folks.

Tweets to look out for

Tweets to look out for

If you get tweets from users unknown to you personally, even if re-tweeted by your friends, you should ignore these posts and certainly not click on any links within them. Remember, the wording of the tweets could be changed at any time, so be aware of your clicks and you should be good-to-go.

How this attack works

This particular attack involves a web site running a Java applet. This applet will attempt to run some commands on the victims machine and in this case will install a key logger which runs on the background on the victims machine and quietly logs all key strokes made by the user on his/her keyboard. These logs will later be analyzed by attackers to capture credentials for banking websites.

You can protect yourself against this type of attack in two ways…

  1. Disable the Java plugin from your browser. I have heard this option popping up from time to time, but unlike the Adobe Reader/Acrobat plugin, you will need the Java plugin to actually use websites you visit. This option should only be used if you understand that you will probably affect your overall web experience. It is not always possible to download all of the applets you will encounter online and then run them in a more protective environment (i.e. VM).
  2. Ensure you do not click OK/RUN when prompted by the Java plugin to execute applets unless you know that it can be trusted. This is the much better option, but it takes a little forethought before hand. You need to understand that Java applets will not execute unless you allow them to do so. So, if you do not trust the applet/application, simply click NO/CANCEL instead.

Although I am all about keeping the plugins as light as possible in number for the browsers to avoid security issues overall, there are a couple of plugins that you will most undoubtedly need including Java and Flash. (and NoScript and AdBlock 🙂 Also, please keep your Java installation up-to-date by ensuring that you keep up with the patches. Currently, we are at 1.6.0_20 of the Oracle/Sun plugin, which can be downloaded from java.sun.com.

PHP5 stdClass assignment gotcha

In PHP 5 all objects are assigned by reference, meaning the = and => operators don’t make a copy but instead cause both variables to refer to the same place in the symbol table. This is useful, because objects are arbitrarily complex structures for which a bit-wise copy of the memory allocated might well not make a valid new object. If you want a copy, use the clone operator, implementing the method __clone() for the class if necessary.

This has some nice consequences; class object creation now looks like:

$foo = new Bar();

rather than (in PHP4)

$foo =& new Bar();

By the way the comparison operator == will return true if two objects have the same attributes and values and are instances of the same class, whereas the identity operator === will return true only if the two objects refer to the same instance of the same class.

PHP5 is not an Object Oriented Language, but just the same it is being used as and OOL, and it has language constructs which facilitate that. If you’re like me, though, you tend to use stdClass objects not as simple class instances but as PHP’s answer to what is called a record or struct in other languages. This can cause confusion, especially when assignment doesn’t go quite as planned.

Here’s the thing:

function works() {
    $coord->x = rand();
    $coord->y = rand();
    return $coord;
}

Each time works() is called a new $coord instance is created and a reference to it is returned from the function. When $coord goes out of scope that returned reference is the only one.

function fails() {
    $stars = array();
    for( $i = 0; $i < 10; $i++ ) {
        $coord->x = rand();
        $coord->y = rand();
        $stars[] = $coord;
    }
    return $stars;
}

The problem here is that each element of $stars[] is a reference to the same object, the same one that’s called $coord. So fails() will return an array of ten identical coordinates, the ones produced in the last loop iteration.

The solution is simple – use clone. The function becomes:

function fails() {
    $stars = array();
    for( $i = 0; $i < 10; $i++ ) {
        $coord->x = rand();
        $coord->y = rand();
        $stars[] = clone $coord;
    }
    return $stars;
}

Adobe hits us again.

The Launch command

Back in 2008, Adobe decided to allow for opening attachments within their document format PDF using external applications (ISO PDF 32000-1:2008). For example, if you attached a nice Excel spreadsheet to your PDF presentation, Adobe Reader or Acrobat would use Microsoft Word, Star Office, or Open Office to open the Excel document. Adobe added this “feature” called Launch to the PDF specifications for enhancement reasons, but the entire effort was short sighted from the get-go.

Although, it sounds nice to have the ability to use other applications to open attachments, it also opens the PDF specification to abuse from those “evil” hackers out there. We have been bombarded constantly since last year with Adobe issues from Acrobat/Reader to Flash. This is only the newest issue in a long line of hardships for (poor?) Adobe. Launch can be used to execute commands from the PDF document, normally to open Word or whatever to view the attachment. Although designed for benign use, this can also be used to execute just about anything on your machine. Because the PDF specification is platform independent meaning there are PDF readers for Windows, Mac, and Linux platforms, all of them conform to the same specifications laid out by Adobe. So, all of these OSs are prone to the attack using this vulnerability in the PDF spec.

A sample, but real attack and how to disable Launch

The attack goes a little like this: Someone sends you a PDF attachment in an email. This email could be a targeted-spearphishing attack which specifically targets your company or organization with a subject line that goes something like “Your account has been disabled”. The PDF looks harmless enough from the outside, possibly giving instructions to perform some actions on your computer or simply “Open the Attachment” or in very large text. What is happening under the hood though is very worrisome as it builds on previous attack vectors using Adobe products and using the Launch command which…

  1. Reads the PDF document for commented out code. Comments in PDF’s are signified by a % character. To execute this command, the PDF Launch command will execute everything at first using cmd.exe. So, this particular attack is Windows-based, but remember — this could easily be /bin/cat as well; affecting many other OSs.
  2. All of the comments are written to a file named script.vbs. The comments are doubly commented, so the Launch command, actually using cmd.exe to do this, also reads the comments (again) removing the comments characters and writing a file named batscript.vbs.
  3. The final step for the PDF to do is execute the script.vbs and batscript.vbs files it just wrote.

So, what do these VBScripts do? They write a new file named game.exe which is actually virus, but it could be anything really at the end of the day. The point here to take away from all of this is to not trust Adobe’s Launch feature at all. Users should disable the automatic launch of external applications to open attachments by…

Trust Manager Preferences

  1. In Adobe Reader and Acrobat, click Edit menu then click Preferences.
  2. In the Trust Manager Category, uncheck Allow opening of non-PDF file attachment with external applications box.

Adobe fail part deux

Another issue here is how Adobe short-sighted the design of Reader/Acrobat so that attackers could use this attack more efficiently. When a PDF has a Launch command within it, Reader/Acrobat will ask you whether or not you would like to execute the command(s). Adobe will list the command verbatim within a multi-lined textbox which is not disabled, but looks like it should be as it is grayed-out. Unfortunately, since Adobe lists the command(s) verbatim, an attacker can insert whitespaces and/or carriage-returns which, in combination with the appearance of a grayed-out textbox, hides the commands from the user. Because this is a targeted-spearphishing attack, the user will likely open the document, see the obfuscated commands as “Click the open button to continue…” or something and click to execute the commands unknowingly infecting themselves with a virus. This is a real design flaw by Adobe which only exacerbates the overall security issues already present in their products.

If you disable the automatic opening of attachments with external applications, as shown above, you will instead be prompted with a simple dialog which states that these commands were designed to be executed but didn’t. This should protect you from the attack vectors laid out above. You can always detach PDF attachments and open them separately using the applications themselves (i.e. Word) without using the built-in Adobe Launch command.

For more information, see Adobe’s response to this attack: Didier Stevens on the Launch Function.

Adding custom status notifications to Shopp

I use Shopp on a number of websites. As a cart, I’d say it’s “mostly there”, but occasionally, I find ways to extend the system to make it more functional. One of the additions that I find customers requesting regularly is the ability to make custom email templates based on the status of an order.  Currently (as of version 1.0.17), Shopp can notify the customer if an order changes status (such as moving from ‘Pending’ to ‘Completed’).

Note: This addition is for Shopp version 1.0.17. You must be using Theme Templates in Shopp to use this technique.

Enabling custom theme templates in shopp
Make sure you use custom templates in shopp if you want to use this technique

Also, since we are editing core Shopp files, you must remember that any Shopp upgrade will remove this feature from your installation.  You’ll have to reapply it after every upgrade.  Our hope is that the future versions of Shopp will have this functionality built into the core.  Any change to your core Shopp files is potentially dangerous, make sure you back up your database and your files before starting!

Looking at the notification.html template the status simply stated as:
[html]
<h1>[sitename] Order Update</h1>

<p class="status">Your order is now: [status]</p>
[/html]

regardless of the status the order is currently in. We would like this to be custom text that indicates more to the customer than just our predefined status name.

In this example, we’ll create a special template to send out when we would like to inform a customer that the order is now “Completed”. In your theme subdirectory, copy the notification.html file into notification-completed.html.  Since we are using the php “strtolower” function in the Shopp core code, your templates should be saved all lowercase (notification-completed) instead of the names as they appear in the menu (notification-Completed.html).  Remove the “Your order is now: [status]” line from the html in your new template, replacing it with the desired text:

[html]
<pre><h1>[sitename] Order Update</h1>

<p class="status">We have dropped your order into the mail. You should receive your package within a week!</p></pre>
[/html]

Now that your new template is ready to be used, you must edit the core of Shopp to read the new template.  Open up wp_content/plugins/shopp/core/flow.php and find (around line 839):

[php]

shopp_email(SHOPP_TEMPLATES."/notification.html", $notification);

[/php]

Replace this code with:

[php]
if( file_exists(SHOPP_TEMPLATES."/notification-".strtolower($labels[$Purchase->status]).".html") ) {
shopp_email(SHOPP_TEMPLATES."/notification-". strtolower($labels[$Purchase->status]). ".html", $notification);
}
else {
shopp_email(SHOPP_TEMPLATES."/notification.html", $notification);
}
[/php]

Now the new notification html file will be used.  You can use this for both the standard status states in Shopp, or you can add/edit your own in the “General” tab of Shopp’s settings in your wordpress backend.  

Shopp status menu

You can edit/add/delete custom status states in Shopp

A custom template can be created for each status you edit/create.  If no template is found in the theme directory, the standard template will be used. You are not limited to just editing the status line in your custom notification template, you can change any text in the html file to reflect your business model.

Once this has been completed and saved back to your server, the new templates should be live and ready to go.  Don’t forget to test this as a customer to your shop.

Last week I talked about the USPS Plugin, and a fix for international orders to Britain. Stay Tuned, there are more shopp articles coming.

If you are interested in hiring us for Shopp customizations or other design / programming needs, send us a message.

Shopp USPS plugin and the British Empire

KOL Discovery entering Vancouver Harbour Feb 05-09 3PM

photo credit: Grantsviews

If you are a fan of Shopp (http://shopplugin.net/), you’ve probably been happy that there’s a built-in solution for shopping carts from inside the WordPress interface.  You’ll also be happy to learn that it’s themeable and extendable much like WordPress itself.  But you are also going to be aware that quite a few features are there, but just haven’t been polished enough to work out of the box.  Shopp is young, and while it doesn’t have the bloat of old standbys such as Opencart or Zen Cart, it doesn’t have the patches and bug fixes for a completely bumpless ride, either.

In this ongoing series, I’m going to document my bouts with Shopp and, more importantly, my solutions to the problems I have found.

Yesterday, a client had a customer from Kent, GB who had a checkout error during shipping computation:

USPSRates: Missing value for Country.

They fell back to our other shipping method, UPS, which happened to compute to $77 from our US location.  The customer emailed, asking if we were crazy, and the process went up the chain to me.

Poking in the the /wp-content/plugins/shopp/plugins/USPSRates.php file, I noticed that the Shopp developers had already included some code to try to handle GB/UK:

[php]
$country = $countries[$country][‘name’];
if ($countries[$country] == "UK") $country .= ‘ (Great Britain)’;
[/php]

But this didn’t quite handle the situation, which sets $country to ‘United Kingdom (Great Britain)’. Looking further down the plugin code, I saw that they were not using the $country variable when sending data to USPS:

[php]
$_[] = ”.$countries[$country][‘name’].”;
[/php]

Looking at the USPS website Postal Codes Listing, there are many codes for shipping to Great Britain, including the “United Kingdom (Great Britain)”. My change that worked was setting the following up, directly in the international part of the site:

Find:

[php]
$_[] = ”.$countries[$country][‘name’].”;
[/php]

and replace with:

[php]
if($country == ‘United Kingdom’){
$_[] = ‘Great Britain and Northern Ireland’;
}
else {
$_[] = ”.$countries[$country][‘name’].”;
}
[/php]

This only solves the issue for shipping to Great Britain, and quite a few of the USPS names are different from the ones stored in Shopp. The real solution is for the database to store the alternate names for countries as USPS calls them. In the meantime, I believe I’ll make an array inside the USPSRates.php file, and map the correct names to the correct USPS names for international shipping. I’ll post that full patch here when I do it.

The shipping plugins for Shopp are an additional nominal charge (In USPS’s case, it’s $25) from the Shopp website..  You’ll have to have an API key from USPS to use the plugin.

If you are interested in hiring us for Shopp customizations or other design / programming needs, send us a message.