Sunday, October 10, 2010


This weekend I attended HacKidCon with my 5-year-old. Overall, it was a very well put-together con, and we would definitely attend again.

The favorite was the "Maker" session with Larry Pesce from PaulDotCom, in which the kids did a basic electronics project consisting of an LED "firefly" in a jar, then built a pneumatic marshmallow cannon. (I'd say the marshmallow cannon was probably the biggest hit of the weekend.) The session was clearly well-planned, and the execution was flawless.

Other high points included magician Mike Bent, building and racing Lego Derby, and a Brazilian Jiu-Jitsu session with instructors from Mass BJJ.

There was plenty of food, and more importantly coffee, so that worked out very well.

One interesting note was that there were a couple of Lego Mindstorms sets just sitting out in an unused area, and they ended up being a huge hit. It seemed like a bit of an afterthought, but it actually provided a much-needed diversion for the kids AND the adults.

Suggestions for next time:
  • Two days is probably a little much for the younger kids. By day 2 we were both tired and cranky, and ended up leaving in the early afternoon.
  • There should probably be some more physically-oriented activities to let the kids blow off steam. They created their own by tearing around the main hallway throwing footballs at each other, which was probably not ideal. The BJJ session was good, but it would be nice if there was something running throughout the day.
  • More unstructured "village"-type activities. I think some of the sessions would have worked better that way, especially considering that the kids all had parents with them for help. For example, if we could have dropped in, sat at a computer, and worked on some of the programming language activities with a manual and an instructor available for questions, I think it would have worked better.
  • Related: I don't think one can expect kids to sit in front of a pile of computers, robots, electronics, etc. and expect them to wait while they pay attention to some slides.
  • 45 minutes is about the longest a 5-year-old can sit and listen to a lecture, and even that is pushing it. I really don't think the standard conference talk format works well here, though I was surprised how interested the little one was in some of the topics related to online safety.
These aren't complaints, though. Overall, HacKid was very well-executed, and all the kids seemed to have a great time. I have to tip my hat to the organizers and sponsors for a job well done. See you next year!

Thursday, June 10, 2010

Juniper SSL VPN - SSL cipher suites

Juniper's SSL VPN continues to baffle me by doing inexplicably weird things. For example, you can tell it not to use weak ciphers, which is good. But it doesn't actually shut them off. It continues to let you negotiate an SSL session with weak ciphers, but then the SSL VPN itself gives you an error message: "This site requires Strong ciphers. Please upgrade your browser."

Ok, so maybe that's kind of user friendly, but I wouldn't be surprised if it was exploitable as well.

Saturday, June 5, 2010

Like A Boss

I will be talking about JBoss fail at DEFCON 18. Hope to see you there!

Wednesday, March 24, 2010

How to Manually Add a Movie Title to Boxee

I've started using Boxee and it is really amazing. There's one small but very annoying issue I've come across. When Boxee indexes a movie or TV show, it attempts to go out and find the information about the file from IMDB. This usually works fine, but when it fails, there's no way to manually resolve it. This means that the media that fails to resolve does not appear in the appropriate menu. The ability to manually set this information is apparently coming, but in the meantime, here's how to do it manually.

You will need a way to edit SQLite database files, such as SQLite Database Browser.

The database file you want to edit is located at

Linux: ~/.boxee/UserData/
Mac OS/X: ~/Library/Application Support/BOXEE/UserData/
AppleTV: ~/Library/Application\ Support/BOXEE/UserData/
Windows Vista: C:\Users\\AppData\Roaming\BOXEE\userdata\
Windows XP: C:\Documents and Settings\\Application Data\BOXEE\userdata\

IMPORTANT: Back up the boxee_catalog file before editing!!

You will want to edit the video_files table.

Add a new row to the table. The idVideo value should automatically increment to the next available value, but you may want to verify this.

You do not have to fill in all the fields. These are the fields I used. I didn't really experiment to find out which ones were required.

Start up Boxee, and the new movie appears!

Monday, February 22, 2010

JBoss Attacks

Read this first:
Hacking Unprotected JBOSS JMX Console Installations

An unprotected JMX console is a serious problem that doesn't get much attention. There are about a million Google dorks you can use to find one (or several). In addition to the ones in the linked post, I like:
inurl:"HtmlAdaptor" inurl:"maindeployer"
intitle:"tomcat status" inurl:8080

And of course you can find unprotected JMX consoles in any other number of ways. This will allow you to do things like shut down servers or deploy your own J2EE apps.

What I also noticed was interesting though, is that this functionality is completely CSRF-able. So even if YOU can't get to a particular site's JMX console, you may be able to CSRF someone else who can. Unfortunately there's no persistent authentication, so it might not be completely reliable; but it's a nice trick if you can make it work.

<img src="http://jbosshost:8080/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system%3Atype%3DServer&methodIndex=0" />

Monday, February 1, 2010

This Old Wordpress Worm

In my quest for some ammo to support my anti-Wordpress rants here in the office, I thought it would be a good idea to try to reproduce the exploit that was going around in that infamous Wordpress worm last summer. Turned out to be a little more time-consuming than I thought it would be, but also pretty interesting.

I wanted to get this done in the laziest way possible, so I used all of the information available that would keep me from having to actually read or understand any code, or you know, do any hard work at all.

The official post on the matter provided a lot of the necessary information, going into detail about the high-level functionality.
"This particular worm, like many before it, is clever: it registers a user, uses a security bug (fixed earlier in the year) to allow evaluated code to be executed through the permalink structure, makes itself an admin, then uses JavaScript to hide itself when you look at users page, attempts to clean up after itself, then goes quiet so you never notice while it inserts hidden spam and malware into your old posts."
Since I don't care about the payload, all I need to know is:
1. It requires a registered user
2. It exploits a previously resolved security bug
3. The attack vector is through the permalink structure
4. It has something to do with eval'ed code

A couple of additional blog posts provided sufficient detail to get started, notably which provided the HTTP logs of the attacker's activity.

The first action is a call to /wp-login.php. That's just going to be logging in the registered user.

The second action is a post to /wp-admin//options-permalink.php. That's the page that modifies the permalink structure. Notice the extra slash. That provides an authorization bypass allowing a normal user to modify the permalink structure. I didn't bother looking any further into the mechanics, and just took this one as a gimme.

We are provided the payload that goes into the permalink structure, something like: %&({${eval(base64_decode($_SERVER[HTTP_REFERER]))}}|.+)&%/

Since this makes no sense to me right at the moment, I'm going to go back to the WP Trac system and try to find some more information. This was after the fact of the worm in question, but nevertheless very helpful.

So we now know that we want to hit an eval() in either classes.php or rewrite.php.

Looking at the worm's third action, it looks like it posts to xmlrpc.php, so we'll try to see if we can get there from here.

Looking at rewrite.php first, the eval() in rewrite.php is called in the url_to_postid() function.

// Substitute the substring matches into the query.
eval("\$query = \"" . addslashes($query) . "\";");

Referencing back to xmlrpc.php, we can see that url_to_postid() is called from the pingback functions, which is just perfect!

if ($post_ID = url_to_postid($pagelinkedto)) {

The XML-RPC method is '' and it takes the "linked from" URL and "post linked to" URL as parameters. Since the "post linked to" parameter is the one that url_to_postid() operates on, that's the only one we need to get right.

Now the only question is: how is the url_to_postid() function actually constructing the $query variable to be eval()'ed?

I'm not sure how to explain how the rewrite rules and associated filters get loaded, so I'll instead provide the following code and output:

$rewrite = $wp_rewrite->wp_rewrite_rules();

array(87) {
string(18) "index.php?robots=1"
string(19) "index.php?feed=atom"
string(118) "index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&name=$matches[4]&%evil%$matches[5]&tb=1"

Check out what happens. If the token we put into the permalink structure (%evil%) isn't understood, it's included verbatim in the query string. This is what's later going to be eval'ed.

So, back to url_to_postid(). When rewrite rules are enabled, it will loop through each rewrite rule trying to match against our query. If we get a match, we get to eval() the query string.

foreach ($rewrite as $match => $query) {
if ( preg_match("!^$match!", $request_match, $matches) ) {
$query = preg_replace("!^.+\?!", '', $query);
eval("\$query = \"" . addslashes($query) . "\";");

So what we want to do is match our request to one of the regex patterns whose resulting query contains the code we want to eval(). Reading that sentence makes my head hurt, but it's really pretty simple.

One thing that's interesting is that we're going to have a lot of the characters we'd want to use stripped out. The way the attacker did it was actually pretty cool:

or, easier to read:


First off, what's the mechanism through which evil() gets executed? The PHP docs are pretty weak on this point, but this was a handy little guide:

Now, why the regex-y looking parens and extra chars? Turns out if we want to include a dollar sign to indicate a PHP variable, that will break the regex matching, being a special character meaning "end of line". What the extra characters allow us to do is to turn the match into an OR which will match anything between %& and &%.

Speaking of which, I still haven't figured out why we need the ampersands. Might just be a delimiter. I didn't use them.

As a proof-of-concept, I modified my permalink structure to look like:


Then posted the following to xmlrpc.php

<?xml version="1.0" encoding="iso-8859-1"?>

Which triggered the phpinfo() call. From there we can include any payload to execute arbitrary code.

I do want to call out the original attacker's payload as particularly clever (decode a base64-encoded referer header, and eval it.)

Friday, January 8, 2010

Don't Cry Wolf

I often find myself in a position that's doesn't fit the security guy stereotype, the position of devil's advocate. In an organization that's heavily populated by engineering types, it's fairly common that a spike in traffic or an unexpected outage will be met with cries of "hackers! break-ins! denial of service!" and such. In these cases, I'm very deliberate in making sure that we have the facts before I pull the security incident alarm.

As a security team, we only have so much goodwill to spend on security incidents. The first time we report one, the organization will pull out all the stops to make sure we have the resources we need to address it. As time goes on, the enthusiasm fades. The sure way to make sure we NEVER get any help on an incident is to start reporting false positives. Think about it... we report a denial-of-service, then eventually realize it was actually a misconfigured system causing the bad traffic. If this happens a couple of times, eventually the organization will treat it exactly like we treat a car alarm going off in the parking lot: "ignore it, eventually it'll shut off on its own."

Obviously, if you see data being destroyed or going out the door, feel free to yell as loud as you can and pull out all the stops. But if you're just not sure, grab a couple of people you trust to help, and get the facts first. Spend your resources wisely. When the real thing hits, you'll be glad you did.

Friday, January 1, 2010

Thoughts on 2010

Another decade come and gone. There are really just a few goals I have for myself in 2010, security-wise.

1. Ditch conventional wisdom

I find myself performing or recommending some "best practices" that, frankly, make me feel a little dirty. I intend to start looking at risk with a much more critical eye. (Just for example, I'm not sure I really believe XSS is as critical as the companies selling web app security products would tell you.)

2. Get actionable

This is more of a work thing. I've done a lot of work to increase the volume of security information available. My goal for this year is, in addition to building out more info-gathering capability, to really get to work on automating to the point where important information is correlated and alerted upon automatically. No more digging through irrelevant information looking for the real stuff.

3. Get back to basics

In the last couple of years, I've really gotten away from vulnerability research and exploit development, which is too bad because that's really what I am most interested in. I plan to devote some time to those activities this year.